get-esbuild-options.html 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. {{/*
  2. ## Overview
  3. This helper returns options dictionary used to configure ESBuild.
  4. The following configurations are set:
  5. * Enable JS minification.
  6. * Enable source map if not building for production.
  7. * Prepare `process.env.<ENVIRONMENT VARIABLE>` defines based on enabled features.
  8. This allows ESBuild to optimize JS bundle size by removing code related
  9. to unused features.
  10. * Added `process-shim.js` so `process.env` is defined.
  11. This way we don't have to explicitly specify every environment
  12. variable via `defines` value.
  13. * Prepare `params` for feature and service configs used in JS.
  14. For more details on ESBuild configuration, see: https://gohugo.io/hugo-pipes/js/
  15. ## Detailed Concepts
  16. ### `feature` and `service`
  17. Features configured in site wide `config.yml` file under `params.features` section.
  18. A **feature** provides a certain functionality to the user via one or more services.
  19. A feature be can enabled or disabled.
  20. A **service** is a 3rd party service, or JS library that implements a feature.
  21. For example, `analytics` is considered a feature.
  22. There are many services that can provide this feature, to name a few:
  23. * Google Analytics
  24. * Counter.Dev
  25. * GoatCounter
  26. To maximize extendibility and therefore usefulness as an open source project,
  27. it is important to define a standard interface that is easy to understand,
  28. configure, and extend.
  29. In this file, I took the liberty of standardizing this interface under `params.features`.
  30. Please note that this breaks compatibility with previous versions of `config.yaml`.
  31. I will provide sample `config.yaml` files with fully documented features, as well as
  32. documentation on migrating the `config.yaml` file to the new standard.
  33. Here is a sample config file for the new `params.features` section. Notice that each `service`
  34. is a dictionary with `enable` and `services` key. `services` is a dictionary with each key
  35. corresponding to a concrete service, and value as configuration / settings. In the case of
  36. services that need no configuration, an empty dictionary is created.
  37. ```yml
  38. params:
  39. features:
  40. # This is the `analytics` feature
  41. analytics:
  42. # This feature is enabled
  43. enable: true
  44. # List of services to enable
  45. services:
  46. # Google Analytics is enabled
  47. google:
  48. # settings for Google Analytics
  49. id: G-xxxxx
  50. # # Counter Dev is disabled
  51. # counterDev:
  52. # id: foo
  53. # name: bar
  54. # [Deprecated] The `darkMode` feature
  55. # This is a deprecated setting, but has not been removed to maintain backward compatibility
  56. # If `theme` is set, the `darkMode` setting will be discarded.
  57. darkMode:
  58. enable: true
  59. # The `theme` feature
  60. theme:
  61. enable: true
  62. services:
  63. light: true # enable light theme. default "true"
  64. dark: true # enable dark theme. default "true"
  65. default: system # can be either light, dark or system. default "system"
  66. This helper will convert the above config into the following env vars:
  67. * `FEATURE_ANALYTICS=1`
  68. * `FEATURE_ANALYTICS_GOOGLE=1`
  69. * `FEATURE_DARKMODE=1`
  70. * `FEATURE_THEME=1`
  71. In JS, you can use it like this:
  72. ```js
  73. import * as params from '@params';
  74. if (process.env.FEATURE_ANALYTICS) {
  75. // Do things to enable this feature here
  76. if (process.env.FEATURE_ANALYTICS_GOOGLE) {
  77. // Do things things to enable google analytics
  78. }
  79. }
  80. ```
  81. You can also access service configs via params:
  82. ```js
  83. import * as params from '@params';
  84. console.log(params);
  85. ```
  86. You will see console output like below. Note, each service configuration is
  87. namespaced by their corresponding feature.
  88. ```json
  89. {
  90. "analytics": {
  91. "google": {
  92. "id": "G-xxxxx"
  93. }
  94. },
  95. "darkmode": {
  96. "darkreader": {
  97. "defaultColorScheme": "system",
  98. "fixes": {
  99. "invert": "['img[src$=\".svg\"]']"
  100. },
  101. "theme": {
  102. "brightness": 100,
  103. "contrast": 100,
  104. "sepia": 0
  105. }
  106. }
  107. }
  108. }
  109. ```
  110. */}}
  111. {{/* Holds all the feature flag environment variables for `process.env.*` in JS land */}}
  112. {{ $defines := dict }}
  113. {{/* Holds all the feature configuration variables exposed to JS side */}}
  114. {{ $params := dict }}
  115. {{/* set NODE_ENV depending on if we are building for production use. */}}
  116. {{ $defines = $defines | merge (dict
  117. "process.env.NODE_ENV" (cond hugo.IsProduction `"production"` `"development"` )
  118. )}}
  119. {{/* Go through each feature defined in our config.yml/config.toml/config.json file. */}}
  120. {{ range $feature, $featureDef := site.Params.features }}
  121. {{/* Initialize a dictionary that will hold all service configs for this specific feature */}}
  122. {{ $featureParams := dict }}
  123. {{ with $featureDef }}
  124. {{/* convert feature name to uppercase and remove '_', e.g. `darkMode` becomes `DARKMODE` */}}
  125. {{ $featureName := replace $feature "_" "" | upper }}
  126. {{/* The feature is enabled if the `enable` key is absent, or is set to `true` */}}
  127. {{ $featureEnabled := or (not (isset . "enable")) .enable }}
  128. {{/* Sets `FEATURE_<FEATURE_NAME>` env var to "1" or "0" depending on if the feature is enabled. */}}
  129. {{ $defines = $defines | merge (dict
  130. (printf "process.env.FEATURE_%s" $featureName) (cond $featureEnabled `'1'` `'0'`)
  131. ) }}
  132. {{ if $featureEnabled }}
  133. {{/* Loop through each service under this feature */}}
  134. {{ range $service, $config := .services }}
  135. {{/*
  136. We assume all services are enabled. To disable a service,
  137. simply comment it out from `config.yaml`.
  138. */}}
  139. {{/* Convert name to all uppercase, removing underscore */}}
  140. {{ $serviceName := replace $service "_" "" | upper }}
  141. {{/* let JS side know this service is enabled */}}
  142. {{ $defines = $defines | merge (dict
  143. (printf "process.env.FEATURE_%s_%s" $featureName $serviceName) `'1'`
  144. ) }}
  145. {{/* add service configuration to feature params */}}
  146. {{ $featureParams = $featureParams | merge (dict $service $config) }}
  147. {{ end }}
  148. {{/* add feature params to top level params */}}
  149. {{ $params = $params | merge (dict $feature $featureParams) }}
  150. {{ end }}
  151. {{ end }}
  152. {{ end }}
  153. {{
  154. return dict
  155. "defines" $defines
  156. "params" $params
  157. "minify" true
  158. "sourceMap" (cond hugo.IsProduction "" "inline")
  159. "inject" "scripts/process-shim.js"
  160. }}