Do the mounts in an imported module's config.yaml need to be copied into your module's config.yaml?

It doesn’t seem to work without doing that, but I don’t see this documented anywhere.

I think it’s no, but you’ll need to make sure the mounted files present on the target module.

Take gohugoio/hugo-mod-bootstrap-scss as an example.

The scss and js folder should be included (committed) on the imported module github.com/twbs/bootstrap.

IMHO, it’s not recommend mounting node_modules in a module.

In this case, the mounted files are from node_modules, which isn’t checked in. There’s a package.hugo.json in the imported module and the importer module, both in sync. npm install is run before hugo build to ensure that node_modules is present. But the files aren’t being mounted by the imported module, despite the mounts being in its config.yaml.

IMHO, it’s not recommend mounting node_modules in a module.

Why? And which module do you mean, the importer or the imported?

The imported module should include files mounted by the importer. You can test it with the following sample.

$ git clone -b mods-mounts https://github.com/razonyang/testing
$ cd testing/site
$ hugo

...
WARN 2023/03/20 08:12:21 [mod] bar's bar/js/index.js mounted
WARN 2023/03/20 08:12:21 [mod] bar's bar/scss/index.scss mounted
...
$ cat layouts/index.html 
{{ range resources.Match "bar/**/*" }}
  {{ warnf "[mod] bar's %v mounted" . }}
{{ end }}
{{ range resources.Match "bootstrap/**/*" }}
  {{ warnf "[mod] bootstrap's %v mounted" . }}
{{ end }}
$ cat config.toml
...
[[module.imports]]
path = "github.com/razonyang/testing/fizz"

$ cat ../fizz/hugo.toml
...
[[module.imports]]
path = "github.com/razonyang/testing/bar"
[[module.imports.mounts]]
source = "node_modules/bootstrap"
target = "assets/bootstrap"
[[module.imports.mounts]]
source = "src"
target = "assets/bar"

$ tree ../bar
├── go.mod
├── go.sum
├── hugo.toml
└── src
    ├── js
    │   └── index.js
    └── scss
        └── index.scss

$ tree .
...
├── node_modules
│   └── bootstrap
│       └── dist
│           └── index.js
...

As the example shown.

  1. site imported fizz module.
  2. fizz imported the bar module, and mounted bar’s src and node_modules/bootstrap.
  3. but the node_modules/bootstrap doesn’t exist on the bar module, so there are no files to mount into assets/bootstrap, even if there is node_modules/bootstrap on the site.

You can verify this by creating files under the bar/node_modules/bootstrap folder.

$ mkdir -p ../bar/node_modules/bootstrap/js/
$ touch ../bar/node_modules/bootstrap/js/index.js
$ hugo
...
WARN 2023/03/20 08:27:44 [mod] bar's bar/js/index.js mounted
WARN 2023/03/20 08:27:44 [mod] bar's bar/scss/index.scss mounted
WARN 2023/03/20 08:27:44 [mod] bootstrap's bootstrap/js/index.js mounted
...

It’s no need to use module to mount node_modules, Hugo can resolve the dependencies from node_modules.

I’m not sure I understand what your example shows. There aren’t any files in GitHub - razonyang/testing: Just for testing now. It seems like you described this first:

site/ # module
  layouts/index.html:
    print files mounted in bar/ and bootstrap/
  config.yaml:
    import fizz
  node_modules/bootstrap/dist/index.js
fizz/ # module
  config.yaml:
    import bar
    mount node_modules/bootstrap to assets/bootstrap
    mount src to assets/bar
bar/ # module
  src/
    js/index.js
    scss/index.scss

This mounts bar/js/index.js and bar/scss/index.scss.

Then you said that creating bar/node_modules/bootstrap/js/index.js would mount bootstrap/js/index.js.

Do I understand correctly?

If so, then I’m wondering: What is the point of the hugo mod npm pack command? This command ensures that the NPM dependencies of imported modules are present in the site’s node_modules. The importer (not imported) module doesn’t necessarily know that some node_modules files need to be mounted so the imported module can use them. So what is the intended effect of hugo mod npm pack? That the presence of an NPM module in the site’s node_modules will have some sort of side effect, and is never actually used concretely in the generated code?

Edit: Removed a question. I realized the answer.

You’ll need to switch to the mods-mounting branch (git clone -b mods-mounts https://github.com/razonyang/testing).

Yes.

This command is not related to module, it pulls the all dependencies of modules to package.json.

As the testing sample shown, the mounted files should be included inside the module, in this case, you’ve to include some node_modules packages inside the module, which is not recommended.

Actually, you could mount some packages as module instead mounting it from node_modules.
Take bootstrap as an example (not tested).

[[module.imports]]
ignoreConfig = true
path = "github.com/twbs/bootstrap"
[[module.imports.mounts]]
source = "scss"
target = "assets/bootstrap/scss"
[[module.imports.mounts]]
source = "dist"
target = "assets/bootstrap/dist"
[[module.imports.mounts]]
source = "js"
target = "assets/bootstrap/js"

You can access the pre-built CSS by resources.Get "bootstrap/dist/css/bootstrap.min.css".

If I remember correctly, your theme will use the pre-built Bootstrap CSS (dist/css/bootstrap.min.css) in some case. You cloud either commit that CSS to module and mount it, or mounting the Bootstrap as a module.

But this make things worse in my point of view, since there are two dependencies managers for same package. The simplest way is to use prebuilt CSS via CDN or always build the CSS via Hugo Pipe.

This command is not related to module, it pulls the all dependencies of modules to package.json .

But what is the point, then? If I import module M, and module M declares in its package.hugo.json that it requires bootstrap, then hugo mod npm pack will generate a package.hugo.json in my module that also requires bootstrap, right? But for what purpose? No code in M can rely on bootstrap being mounted, so what’s the point?

If I remember correctly, your theme will use the pre-built Bootstrap CSS (dist/css/bootstrap.min.css) in some case. You cloud either commit that CSS to module and mount it, or mounting the Bootstrap as a module.

This doesn’t work in general, Bootstrap is unusual in that it commits its build artifacts in a dist directory, but many—perhaps most—projects do not. Katex, for example, does not.

But this make things worse in my point of view, since there are two dependencies managers for same package. The simplest way is to use prebuilt CSS via CDN or always build the CSS via Hugo Pipe.

Live downloading of resources isn’t always desirable or possible.

Hmm, I think I’ve explained the hugo mod npm pack.

You could build it from source code (src) via Hugo Pipes instead of using pre-built assets …


The problem is that you’re trying to mount files from a module, which not present in the module, so you may need to change the way how to build and use assets, to follow the current rule how modules mount files.

Your answer there seemed to imply that the node_modules in the site would be mount-able by the modules themselves. Otherwise, what’s the point?

You could build it from source code (src ) via Hugo Pipes instead of using pre-built assets …

This doesn’t work if it’s an imported module that needs to process the imported and mounted assets.

Hugo will resolve dependencies from node modules, see also JavaScript Building | Hugo and the includePaths of Sass/SCSS, it doesn’t mean there are mountable from a module.