123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- {{/*
- ## Overview
- This helper returns options dictionary used to configure ESBuild.
- The following configurations are set:
- * Enable JS minification.
- * Enable source map if not building for production.
- * Prepare `process.env.<ENVIRONMENT VARIABLE>` defines based on enabled features.
- This allows ESBuild to optimize JS bundle size by removing code related
- to unused features.
- * Added `process-shim.js` so `process.env` is defined.
- This way we don't have to explicitly specify every environment
- variable via `defines` value.
- * Prepare `params` for feature and service configs used in JS.
- For more details on ESBuild configuration, see: https://gohugo.io/hugo-pipes/js/
- ## Detailed Concepts
- ### `feature` and `service`
- Features configured in site wide `config.yml` file under `params.features` section.
- A **feature** provides a certain functionality to the user via one or more services.
- A feature be can enabled or disabled.
- A **service** is a 3rd party service, or JS library that implements a feature.
- For example, `analytics` is considered a feature.
- There are many services that can provide this feature, to name a few:
-
- * Google Analytics
- * Counter.Dev
- * GoatCounter
- To maximize extendibility and therefore usefulness as an open source project,
- it is important to define a standard interface that is easy to understand,
- configure, and extend.
- In this file, I took the liberty of standardizing this interface under `params.features`.
- Please note that this breaks compatibility with previous versions of `config.yaml`.
- I will provide sample `config.yaml` files with fully documented features, as well as
- documentation on migrating the `config.yaml` file to the new standard.
- Here is a sample config file for the new `params.features` section. Notice that each `service`
- is a dictionary with `enable` and `services` key. `services` is a dictionary with each key
- corresponding to a concrete service, and value as configuration / settings. In the case of
- services that need no configuration, an empty dictionary is created.
- ```yml
- params:
- features:
- # This is the `analytics` feature
- analytics:
- # This feature is enabled
- enable: true
- # List of services to enable
- services:
- # Google Analytics is enabled
- google:
- # settings for Google Analytics
- id: G-xxxxx
-
- # # Counter Dev is disabled
- # counterDev:
- # id: foo
- # name: bar
-
- # [Deprecated] The `darkMode` feature
- # This is a deprecated setting, but has not been removed to maintain backward compatibility
- # If `theme` is set, the `darkMode` setting will be discarded.
- darkMode:
- enable: true
-
- # The `theme` feature
- theme:
- enable: true
- services:
- light: true # enable light theme. default "true"
- dark: true # enable dark theme. default "true"
- default: system # can be either light, dark or system. default "system"
- This helper will convert the above config into the following env vars:
- * `FEATURE_ANALYTICS=1`
- * `FEATURE_ANALYTICS_GOOGLE=1`
- * `FEATURE_DARKMODE=1`
- * `FEATURE_THEME=1`
- In JS, you can use it like this:
- ```js
- import * as params from '@params';
- if (process.env.FEATURE_ANALYTICS) {
- // Do things to enable this feature here
- if (process.env.FEATURE_ANALYTICS_GOOGLE) {
- // Do things things to enable google analytics
- }
- }
- ```
- You can also access service configs via params:
- ```js
- import * as params from '@params';
- console.log(params);
- ```
- You will see console output like below. Note, each service configuration is
- namespaced by their corresponding feature.
- ```json
- {
- "analytics": {
- "google": {
- "id": "G-xxxxx"
- }
- },
- "darkmode": {
- "darkreader": {
- "defaultColorScheme": "system",
- "fixes": {
- "invert": "['img[src$=\".svg\"]']"
- },
- "theme": {
- "brightness": 100,
- "contrast": 100,
- "sepia": 0
- }
- }
- }
- }
- ```
- */}}
- {{/* Holds all the feature flag environment variables for `process.env.*` in JS land */}}
- {{ $defines := dict }}
- {{/* Holds all the feature configuration variables exposed to JS side */}}
- {{ $params := dict }}
- {{/* set NODE_ENV depending on if we are building for production use. */}}
- {{ $defines = $defines | merge (dict
- "process.env.NODE_ENV" (cond hugo.IsProduction `"production"` `"development"` )
- )}}
- {{/* Go through each feature defined in our config.yml/config.toml/config.json file. */}}
- {{ range $feature, $featureDef := site.Params.features }}
- {{/* Initialize a dictionary that will hold all service configs for this specific feature */}}
- {{ $featureParams := dict }}
- {{ with $featureDef }}
- {{/* convert feature name to uppercase and remove '_', e.g. `darkMode` becomes `DARKMODE` */}}
- {{ $featureName := replace $feature "_" "" | upper }}
- {{/* The feature is enabled if the `enable` key is absent, or is set to `true` */}}
- {{ $featureEnabled := or (not (isset . "enable")) .enable }}
- {{/* Sets `FEATURE_<FEATURE_NAME>` env var to "1" or "0" depending on if the feature is enabled. */}}
- {{ $defines = $defines | merge (dict
- (printf "process.env.FEATURE_%s" $featureName) (cond $featureEnabled `'1'` `'0'`)
- ) }}
- {{ if $featureEnabled }}
- {{/* Loop through each service under this feature */}}
- {{ range $service, $config := .services }}
- {{/*
- We assume all services are enabled. To disable a service,
- simply comment it out from `config.yaml`.
- */}}
- {{/* Convert name to all uppercase, removing underscore */}}
- {{ $serviceName := replace $service "_" "" | upper }}
- {{/* let JS side know this service is enabled */}}
- {{ $defines = $defines | merge (dict
- (printf "process.env.FEATURE_%s_%s" $featureName $serviceName) `'1'`
- ) }}
- {{/* add service configuration to feature params */}}
- {{ $featureParams = $featureParams | merge (dict $service $config) }}
- {{ end }}
- {{/* add feature params to top level params */}}
- {{ $params = $params | merge (dict $feature $featureParams) }}
- {{ end }}
- {{ end }}
- {{ end }}
- {{
- return dict
- "defines" $defines
- "params" $params
- "minify" true
- "sourceMap" (cond hugo.IsProduction "" "inline")
- "inject" "scripts/process-shim.js"
- }}
|