get-esbuild-options.html 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. # The `darkMode` feature
  55. darkmode:
  56. enable: true
  57. This helper will convert the above config into the following env vars:
  58. * `FEATURE_ANALYTICS=1`
  59. * `FEATURE_ANALYTICS_GOOGLE=1`
  60. * `FEATURE_DARKMODE=1`
  61. In JS, you can use it like this:
  62. ```js
  63. import * as params from '@params';
  64. if (process.env.FEATURE_ANALYTICS) {
  65. // Do things to enable this feature here
  66. if (process.env.FEATURE_ANALYTICS_GOOGLE) {
  67. // Do things things to enable google analytics
  68. }
  69. }
  70. ```
  71. You can also access service configs via params:
  72. ```js
  73. import * as params from '@params';
  74. console.log(params);
  75. ```
  76. You will see console output like below. Note, each service configuration is
  77. namespaced by their corresponding feature.
  78. ```json
  79. {
  80. "analytics": {
  81. "google": {
  82. "id": "G-xxxxx"
  83. }
  84. },
  85. "darkmode": {
  86. "darkreader": {
  87. "defaultColorScheme": "system",
  88. "fixes": {
  89. "invert": "['img[src$=\".svg\"]']"
  90. },
  91. "theme": {
  92. "brightness": 100,
  93. "contrast": 100,
  94. "sepia": 0
  95. }
  96. }
  97. }
  98. }
  99. ```
  100. */}}
  101. {{/* Holds all the feature flag environment variables for `process.env.*` in JS land */}}
  102. {{ $defines := dict }}
  103. {{/* Holds all the feature configuration variables exposed to JS side */}}
  104. {{ $params := dict }}
  105. {{/* set NODE_ENV depending on if we are building for production use. */}}
  106. {{ $defines = $defines | merge (dict
  107. "process.env.NODE_ENV" (cond hugo.IsProduction `"production"` `"development"` )
  108. )}}
  109. {{/* Go through each feature defined in our config.yml/config.toml/config.json file. */}}
  110. {{ range $feature, $featureDef := site.Params.features }}
  111. {{/* Initialize a dictionary that will hold all service configs for this specific feature */}}
  112. {{ $featureParams := dict }}
  113. {{ with $featureDef }}
  114. {{/* convert feature name to uppercase and remove '_', e.g. `darkMode` becomes `DARKMODE` */}}
  115. {{ $featureName := replace $feature "_" "" | upper }}
  116. {{/* The feature is enabled if the `enable` key is absent, or is set to `true` */}}
  117. {{ $featureEnabled := or (not (isset . "enable")) .enable }}
  118. {{/* Sets `FEATURE_<FEATURE_NAME>` env var to "1" or "0" depending on if the feature is enabled. */}}
  119. {{ $defines = $defines | merge (dict
  120. (printf "process.env.FEATURE_%s" $featureName) (cond $featureEnabled `'1'` `'0'`)
  121. ) }}
  122. {{ if $featureEnabled }}
  123. {{/* Loop through each service under this feature */}}
  124. {{ range $service, $config := .services }}
  125. {{/*
  126. We assume all services are enabled. To disable a service,
  127. simply comment it out from `config.yaml`.
  128. */}}
  129. {{/* Convert name to all uppercase, removing underscore */}}
  130. {{ $serviceName := replace $service "_" "" | upper }}
  131. {{/* let JS side know this service is enabled */}}
  132. {{ $defines = $defines | merge (dict
  133. (printf "process.env.FEATURE_%s_%s" $featureName $serviceName) `'1'`
  134. ) }}
  135. {{/* add service configuration to feature params */}}
  136. {{ $featureParams = $featureParams | merge (dict $service $config) }}
  137. {{ end }}
  138. {{/* add feature params to top level params */}}
  139. {{ $params = $params | merge (dict $feature $featureParams) }}
  140. {{ end }}
  141. {{ end }}
  142. {{ end }}
  143. {{
  144. return dict
  145. "defines" $defines
  146. "params" $params
  147. "minify" true
  148. "sourceMap" (cond hugo.IsProduction "" "inline")
  149. "inject" "scripts/process-shim.js"
  150. }}