hugo/docs/content/en/hugo-pipes/js.md

159 lines
5.9 KiB
Markdown
Raw Normal View History

---
title: JavaScript Building
description: Hugo Pipes can process JavaScript files with [ESBuild](https://github.com/evanw/esbuild).
date: 2020-07-20
publishdate: 2020-07-20
lastmod: 2020-07-20
categories: [asset management]
keywords: []
menu:
docs:
parent: "pipes"
weight: 45
weight: 45
sections_weight: 45
draft: false
---
Any JavaScript resource file can be transpiled and "tree shaken" using `js.Build` which takes for argument either a string for the filepath or a dict of options listed below.
### Options
targetPath [string]
: If not set, the source path will be used as the base target path.
Note that the target path's extension may change if the target MIME type is different, e.g. when the source is TypeScript.
params [map or slice] {{< new-in "0.78.0" >}}
: Params that can be imported as JSON in your JS files, e.g.:
```go-html-template
{{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api" ) }}
```
And then in your JS file:
```js
import * as params from '@params';
```
Note that this is meant for small data sets, e.g. config settings. For larger data, please put/mount the files into `/assets` and import them directly.
minify [bool]
: Let `js.Build` handle the minification.
2020-11-03 08:05:09 +00:00
avoidTDZ {{< new-in "0.78.0" >}}
: There is/was a bug in WebKit with severe performance issue with the tracking of TDZ checks in JavaScriptCore. Enabling this flag removes the TDZ and `const` assignment checks and may improve performance of larger JS codebases until the WebKit fix is in widespread use. See https://bugs.webkit.org/show_bug.cgi?id=199866
target [string]
: The language target.
One of: `es5`, `es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020` or `esnext`.
Default is `esnext`.
externals [slice]
: External dependencies. If a dependency should not be included in the bundle (Ex. library loaded from a CDN.), it should be listed here.
```go-html-template
{{ $externals := slice "react" "react-dom" }}
```
Squashed 'docs/' changes from 4895c29c5..9abd3043a 9abd3043a Add docs for shimming JS libraries 6a1c8dcd7 Update sitemap-template.md (#1245) 37c397332 Update frontends.md a0f86f6df Update configuration.md bb00cb2c1 Update page-bundles.md 773212de6 Restructure and simplify fcba7dddf Some minor clarifications of weight sorting 759b967fc Update configuration-markup.md 56708f0b7 module import path remove slash at end 59f4f4acd Doc: Fix typo in hugo command faacf2e97 Clarify pagination documentation (#1208) d8eb60887 netlify: Bump to 0.75.1 8cedf6231 Merge branch 'temp751' 188e2bf56 releaser: Add release notes to /docs for release of 0.75.1 c96d4b7a3 Update index.md 1a9d192f7 Update index.md 32731b916 Update index.md a5bfa0c9a Restore the ... home page b6850bf96 Release 0.75.0 d6e5e624f releaser: Add release notes to /docs for release of 0.75.0 8cd6b4f47 typo: already -> already 2cb2b22bb Merge commit '534ae9c57a902aea9ed6e62390dec11fa74b7122' e3525de23 docs: Regen docs helper fd746dd83 docs: Regenerate CLI docs e20127980 Add "hugo mod npm pack" 8e82c7ce1 markup/highlight: Add support to linkable line anchors on Chroma 21e94911b markup/asciidocext: Fix AsciiDoc TOC with code 50b8dace5 modules: Add noVendor to module config d05b541fe modules: Make ignoreVendor a glob pattern c946082e7 docs: Update replaceRE func 149054341 docs: Update replace func d917567df docs: Update merge function f1e093c92 docs: Regen CLI docs c7bac967d docs: Regen docs helper 7a38f7a45 Merge commit '7d7771b673e5949f554515a2c236b23192c765c8' 1a5a7263a markup/asciidoc: Add support for .TableOfContents git-subtree-dir: docs git-subtree-split: 9abd3043a9214b390e8cc148f4588bf630620851
2020-10-06 14:22:20 +00:00
> Marking a package as external doesn't imply that the library can be loaded from a CDN. It simply tells Hugo not to expand/include the package in the JS file.
defines [map]
: Allow to define a set of string replacement to be performed when building. Should be a map where each key is to be replaced by its value.
```go-html-template
{{ $defines := dict "process.env.NODE_ENV" `"development"` }}
```
format [string] {{< new-in "0.74.3" >}}
: The output format.
One of: `iife`, `cjs`, `esm`.
Default is `iife`, a self-executing function, suitable for inclusion as a <script> tag.
### Import JS code from /assets
{{< new-in "0.78.0" >}}
Since Hugo `v0.78.0` `js.Build` has full support for the virtual union file system in [Hugo Modules](/hugo-modules/). You can see some simple examples in this [test project](https://github.com/gohugoio/hugoTestProjectJSModImports), but in short this means that you can do this:
```js
import { hello } from 'my/module';
```
And it will respolve to the top-most `index.{js,ts,tsx,jsx}` inside `assets/my/module` in the layered file system.
```js
import { hello3 } from 'my/module/hello3';
```
Wil resolve to `hello3.{js,ts,tsx,jsx}` inside `assets/my/module`.
Any imports starting with `.` is resolved relative to the current file:
```js
import { hello4 } from './lib';
```
For other files (e.g. `JSON`, `CSS`) you need to use the relative path including any extension, e.g:
```js
import * as data from 'my/module/data.json';
```
Also note the new `params` option that can be passed from template to your JS files, e.g.:
```go-html-template
{{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api" ) }}
```
And then in your JS file:
```js
import * as params from '@params';
```
Hugo will, by default, generate a `assets/jsconfig.js` file that maps the imports. This is useful for navigation/intellisense help inside code editors, but if you don't need/want it, you can [turn it off](/getting-started/configuration/#configure-build).
### Examples
```go-html-template
{{ $built := resources.Get "js/index.js" | js.Build "main.js" }}
```
Or with options:
```go-html-template
{{ $externals := slice "react" "react-dom" }}
{{ $defines := dict "process.env.NODE_ENV" `"development"` }}
{{ $opts := dict "targetPath" "main.js" "externals" $externals "defines" $defines }}
{{ $built := resources.Get "scripts/main.js" | js.Build $opts }}
<script type="text/javascript" src="{{ $built.RelPermalink }}" defer></script>
```
Squashed 'docs/' changes from 4895c29c5..9abd3043a 9abd3043a Add docs for shimming JS libraries 6a1c8dcd7 Update sitemap-template.md (#1245) 37c397332 Update frontends.md a0f86f6df Update configuration.md bb00cb2c1 Update page-bundles.md 773212de6 Restructure and simplify fcba7dddf Some minor clarifications of weight sorting 759b967fc Update configuration-markup.md 56708f0b7 module import path remove slash at end 59f4f4acd Doc: Fix typo in hugo command faacf2e97 Clarify pagination documentation (#1208) d8eb60887 netlify: Bump to 0.75.1 8cedf6231 Merge branch 'temp751' 188e2bf56 releaser: Add release notes to /docs for release of 0.75.1 c96d4b7a3 Update index.md 1a9d192f7 Update index.md 32731b916 Update index.md a5bfa0c9a Restore the ... home page b6850bf96 Release 0.75.0 d6e5e624f releaser: Add release notes to /docs for release of 0.75.0 8cd6b4f47 typo: already -> already 2cb2b22bb Merge commit '534ae9c57a902aea9ed6e62390dec11fa74b7122' e3525de23 docs: Regen docs helper fd746dd83 docs: Regenerate CLI docs e20127980 Add "hugo mod npm pack" 8e82c7ce1 markup/highlight: Add support to linkable line anchors on Chroma 21e94911b markup/asciidocext: Fix AsciiDoc TOC with code 50b8dace5 modules: Add noVendor to module config d05b541fe modules: Make ignoreVendor a glob pattern c946082e7 docs: Update replaceRE func 149054341 docs: Update replace func d917567df docs: Update merge function f1e093c92 docs: Regen CLI docs c7bac967d docs: Regen docs helper 7a38f7a45 Merge commit '7d7771b673e5949f554515a2c236b23192c765c8' 1a5a7263a markup/asciidoc: Add support for .TableOfContents git-subtree-dir: docs git-subtree-split: 9abd3043a9214b390e8cc148f4588bf630620851
2020-10-06 14:22:20 +00:00
#### Shimming a JS library
Squashed 'docs/' changes from 4895c29c5..9abd3043a 9abd3043a Add docs for shimming JS libraries 6a1c8dcd7 Update sitemap-template.md (#1245) 37c397332 Update frontends.md a0f86f6df Update configuration.md bb00cb2c1 Update page-bundles.md 773212de6 Restructure and simplify fcba7dddf Some minor clarifications of weight sorting 759b967fc Update configuration-markup.md 56708f0b7 module import path remove slash at end 59f4f4acd Doc: Fix typo in hugo command faacf2e97 Clarify pagination documentation (#1208) d8eb60887 netlify: Bump to 0.75.1 8cedf6231 Merge branch 'temp751' 188e2bf56 releaser: Add release notes to /docs for release of 0.75.1 c96d4b7a3 Update index.md 1a9d192f7 Update index.md 32731b916 Update index.md a5bfa0c9a Restore the ... home page b6850bf96 Release 0.75.0 d6e5e624f releaser: Add release notes to /docs for release of 0.75.0 8cd6b4f47 typo: already -> already 2cb2b22bb Merge commit '534ae9c57a902aea9ed6e62390dec11fa74b7122' e3525de23 docs: Regen docs helper fd746dd83 docs: Regenerate CLI docs e20127980 Add "hugo mod npm pack" 8e82c7ce1 markup/highlight: Add support to linkable line anchors on Chroma 21e94911b markup/asciidocext: Fix AsciiDoc TOC with code 50b8dace5 modules: Add noVendor to module config d05b541fe modules: Make ignoreVendor a glob pattern c946082e7 docs: Update replaceRE func 149054341 docs: Update replace func d917567df docs: Update merge function f1e093c92 docs: Regen CLI docs c7bac967d docs: Regen docs helper 7a38f7a45 Merge commit '7d7771b673e5949f554515a2c236b23192c765c8' 1a5a7263a markup/asciidoc: Add support for .TableOfContents git-subtree-dir: docs git-subtree-split: 9abd3043a9214b390e8cc148f4588bf630620851
2020-10-06 14:22:20 +00:00
It's a very common practice to load external libraries using CDN rather than importing all packages in a single JS file, making it bulky. To do the same with Hugo, you'll need to shim the libraries as follows. In this example, `algoliasearch` and `instantsearch.js` will be shimmed.
Firstly, add the following to your project's `package.json`:
```json
{
"browser": {
"algoliasearch/lite": "./public/js/shims/algoliasearch.js",
"instantsearch.js/es/lib/main": "./public/js/shims/instantsearch.js"
}
}
```
What this does is it tells Hugo to look for the listed packages somewhere else. Here we're telling Hugo to look for `algoliasearch/lite` and `instantsearch.js/es/lib/main` in the project's `public/js/shims` folder.
Now we'll need to create the shim JS files which export the global JS variables `module.exports = window.something`. You can create a separate shim JS file in your `assets` directory, and redirect the import paths there if you wish, but a much cleaner way is to create these files on the go, by having the following before your JS is built.
```go-html-template
{{ $a := "module.exports = window.algoliasearch" | resources.FromString "js/shims/algoliasearch.js" }}
{{ $i := "module.exports = window.instantsearch" | resources.FromString "js/shims/instantsearch.js" }}
{{/* Call RelPermalink unnecessarily to generate JS files */}}
{{ $placebo := slice $a.RelPermalink $i.RelPermalink }}
```
That's it! You should now have a browser-friendly JS which can use external JS libraries.