Babel: Cannot find module

Hi all!

This appears to be like I’m missing something really simple, but I can’t figure out what.

In my ./layouts/_default/baseof.html, I have:

<!doctype html>
<!--suppress CssUnknownTarget, HtmlUnknownAttribute, HtmlUnknownTarget -->
<html
  class = "h-full overflow-hidden w-full"
  lang = "en">
  <head>
    <!-- other stuff -->
    <script
      src = "{{- (resources.Get "js/bundle.js" | babel | js.Build | minify).RelPermalink -}}"
      defer>
    </script>
  </head>
  <body>
    <!-- contents -->
  </body>
</html>

I have my tailwind.config.js file in the root of the project along with config.toml.

I have my JavaScript file in ./assets/js/bundle.js:

/* rest of the code */
const tailwindConfig = preval`
  const config = require('tailwindcss/resolveConfig')(require('../tailwind.config.js')).theme
  module.exports = {
    'height-14': parseFloat(config.height['14']),
    'screen-sm': parseInt(config.screens.sm)
  }

I have that setup as per Tailwind’s documentation here: Configuration - Tailwind CSS

Now when I try to run hugo (or hugo server), I get the following errors:

hugo
Start building sites … 
hugo v0.92.0+extended darwin/amd64 BuildDate=unknown
Error: Error building site: BABEL: failed to transform "js/bundle.js" (application/javascript): Error: /Users/hrishikesh/Desktop/ts-v3/js/bundle.js: Cannot find module '../tailwind.config.js'
Require stack:
- /Users/hrishikesh/Desktop/ts-v3/js/bundle.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/helpers.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/index.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/config/files/module-types.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/config/files/configuration.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/config/files/index.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/index.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/cli/lib/babel/options.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/cli/lib/babel/index.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/cli/bin/babel.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Module.require (node:internal/modules/cjs/loader:999:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/Users/hrishikesh/Desktop/ts-v3/js/bundle.js:2:57)
    at Module._compile (node:internal/modules/cjs/loader:1097:14)
    at requireFromString (/Users/hrishikesh/Desktop/ts-v3/node_modules/require-from-string/index.js:28:4)
    at requireFromString (/Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/helpers.js:21:13)
    at getReplacement (/Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/helpers.js:39:15)
    at PluginPass.TaggedTemplateExpression (/Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/index.js:75:29) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/hrishikesh/Desktop/ts-v3/js/bundle.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/helpers.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/index.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/config/files/module-types.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/config/files/configuration.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/config/files/index.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/index.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/cli/lib/babel/options.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/cli/lib/babel/index.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/cli/bin/babel.js'
  ]
}
: failed to execute binary "npx" with args [--no-install babel --filename=js/bundle.js --out-file=/var/folders/q_/6x14rln918d83wdhb2hz0nfr0000gn/T/compileOut-1481260051.js]: Error: /Users/hrishikesh/Desktop/ts-v3/js/bundle.js: Cannot find module '../tailwind.config.js'
Require stack:
- /Users/hrishikesh/Desktop/ts-v3/js/bundle.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/helpers.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/index.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/config/files/module-types.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/config/files/configuration.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/config/files/index.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/index.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/cli/lib/babel/options.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/cli/lib/babel/index.js
- /Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/cli/bin/babel.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Module.require (node:internal/modules/cjs/loader:999:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/Users/hrishikesh/Desktop/ts-v3/js/bundle.js:2:57)
    at Module._compile (node:internal/modules/cjs/loader:1097:14)
    at requireFromString (/Users/hrishikesh/Desktop/ts-v3/node_modules/require-from-string/index.js:28:4)
    at requireFromString (/Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/helpers.js:21:13)
    at getReplacement (/Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/helpers.js:39:15)
    at PluginPass.TaggedTemplateExpression (/Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/index.js:75:29) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/hrishikesh/Desktop/ts-v3/js/bundle.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/helpers.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/babel-plugin-preval/dist/index.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/config/files/module-types.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/config/files/configuration.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/config/files/index.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/core/lib/index.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/cli/lib/babel/options.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/cli/lib/babel/index.js',
    '/Users/hrishikesh/Desktop/ts-v3/node_modules/@babel/cli/bin/babel.js'
  ]
}

Total in 2364 ms

However, this works if I change:

require('../tailwind.config.js')

to

require('./tailwind.config.js')

and move the bundle.js file from ./assets/js/bundle.js to ./assets/bundle.js (and update the reference in ./layouts/_default/baseof.html).

According to Hugo docs:

Any imports in a file outside /assets or that does not resolve to a component inside /assets will be resolved by ESBuild with the project directory as the resolve directory (used as the starting point when looking for node_modules etc.)

when I move my file into ./assets/js/, I should be getting the root of the project as the parent folder. But that doesn’t seem to work. What could I be doing wrong?

It looks like something you will have to put in a test repo to properly get behind it. It has quite a lot of components that go hand in hand here.

First of all, what’s up with the preval` in your first line of bundle.js? Also, the second line looks strange. If you can run this on CLI without Hugo I would assume that Hugo somehow doesn’t understand/translate this?

The point where I would start is this line in the log:

: failed to execute binary "npx" with args [--no-install babel --filename=js/bundle.js --out-file=/var/folders/q_/6x14rln918d83wdhb2hz0nfr0000gn/T/compileOut-1481260051.js]: Error: /Users/hrishikesh/Desktop/ts-v3/js/bundle.js: Cannot find module '../tailwind.config.js'

Someone (Hugo or npm) tries to execute npx to get Babel, which is not installed. My head goes always to “Always install everything either local or global or Hugo won’t find it”. It’s also probably not Hugo who does not resolve the ../tailwind.config.js but Babel or it even does not mean it can’t resolve it but more or less it is not found because beforehand something happens that returns null to whoever expects a configuration object.

I also never tried to connect Babel and JSBuild, as both do more or less the same with different tools. But because the error comes before that point I am not going to pontificate :wink:

Sure, here’s a test repo:

Just like I mention, if I move the JS file to the root of the assets folder and change the require statement of the Tailwind config file, it works fine. But with the current setup of the repo, it does not and I fail to understand why.

preval is a Babel plugin that would pre-evaluate the contents within. So if I need to access the values of my Tailwind theme in my JavaScript, I need to import my Tailwind configuration in there. If I import the entire configuration, my JS Bundle will be bloated as it will contain all colours, values, everything. So, Tailwind recommends using something like this preval plugin that would simply execute the JS within the backticks and export the final output. In my above code,

console.log(tailwindConfig) should give me the output:

{
  'height-14': 3.5,
  'screen-sm': 640
}

Yes, it’s not Hugo, it’s Babel, but from my understanding, the files in the root of the project are automatically available to the files in assets folder. So, when importing them in the ./assets/bundle.js file, I didn’t have to do require('../tailwind.config.js'), but I could instead import it as it’s in the same directory: require('./tailwind.config.js'). So, if I put the file in ./assets/js/bundle.js, I should be able to go to just one folder up ../. So somehow it has to do with how Hugo is making the files available.

I try to avoid it too, but I haven’t really looked for an alternative yet when trying to import values from my Tailwind config.

Another thing to note, if I remove it from that preval thing and try to use it normally like:

const tail = require('../tailwind.config.js')

is still fails.

hugo server
Start building sites … 
hugo v0.92.0+extended darwin/amd64 BuildDate=unknown
Error: Error building site: JSBUILD: failed to transform "js/bundle.js" (application/javascript): Could not resolve "../tailwind.config.js"

This time the error comes from JSBuild instead of Babel.

TLDR:
The hugo --> babel --> preval --> require stack cannot resolve relative paths.

@Hrishikesh

I reduced this to a simple Babel problem:

git clone --single-branch -b hugo-forum-topic-36724 https://github.com/jmooring/hugo-testing hugo-forum-topic-36724
cd hugo-forum-topic-36724
hugo && cat public/js/bundle.js 

The expected output is:

const a = 1;
const b = 2;
const c = 3;
const d = 4;

The test cases and notes are in assets/js/bundle.js.

The Node.JS require documentation states:

The rules of where require finds the files can be a little complex, but a simple rule of thumb is that if the file doesn’t start with “./” or “/”, then it is either considered a core module (and the local Node.js path is checked), or a dependency in the local node_modules folder. If the file starts with “./” it is considered a relative file to the file that called require. If the file starts with “/”, it is considered an absolute path. NOTE: you can omit “.js” and require will automatically append it if needed. For more detailed information, see the official docs.

With the hugo --> babel --> preval --> require stack:

  1. I can require a file that I place in the node_modules directory by omitting a leading “./” or “/
  2. I can require any file with its absolute path
  3. I cannot require a file using the “./” notation

The next step is to determine if this a babel --> preval --> require problem, or a hugo problem, by testing a similar setup with the babel CLI.

Thanks for the thorough testing @jmooring!

However, as per my last comment, I think we can totally remove babel from the equation.

If you take a look at this branch:

Using /assets/bundle.js works, but using /assets/js/bundle.js doesn’t. Do you know what could cause the difference? If I’ve understood correctly, both the files are using relative imports, but one fails while other works.

Same applies to my approach with babel and preval. It works with (./ notation) as long as I don’t nest the file in the js folder.