Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"MODULE_NOT_FOUND" if tailwind config is in another directory #124

Closed
saites opened this issue Jul 24, 2022 · 3 comments
Closed

"MODULE_NOT_FOUND" if tailwind config is in another directory #124

saites opened this issue Jul 24, 2022 · 3 comments
Assignees

Comments

@saites
Copy link

saites commented Jul 24, 2022

What version of @tailwindcss/forms are you using?

v0.5.2

What version of Node.js are you using?

v18.6.0 (via the official node:18 Docker image)

What browser are you using?

N/A

What operating system are you using?

Debian Bullseye container, OpenSUSE host

Reproduction repository

https://github.com/saites/issue-tailwindcss-forms-non-local-config/

Describe your issue

If my config is not in the same directory, but specified with --config, this fails with Cannot find module @tailwindcss/forms. I don't know if this is an issue with the plugin or with tailwindcss. See the example repo for a minimal example, which runs using Docker.

The only difference between the working and failing example is that the failing example uses a non-local config file, whereas the working on uses a config file in the same directory:

[19:42]> diff works.sh fails.sh 
8c8
<        --config /app/tailwind.config.js \
---
>        --config /code/tailwind.config.js \

The actual config files are identical (see the Dockerfile).

Running ./works.sh works:

[19:43]> ./works.sh 
Sending build context to Docker daemon  49.66kB
Step 1/6 : FROM node:18
 ---> 7e9550136fca
Step 2/6 : RUN mkdir /app /code
 ---> Using cache
 ---> f1794cde37ab
Step 3/6 : COPY tailwind.config.js main.css index.html /code/
 ---> Using cache
 ---> 1684c2b33b98
Step 4/6 : RUN cp /code/tailwind.config.js /app/tailwind.config.js
 ---> Using cache
 ---> d160a106acaa
Step 5/6 : WORKDIR /app
 ---> Using cache
 ---> d8443c56b8bf
Step 6/6 : RUN npm install -D tailwindcss @tailwindcss/forms
 ---> Using cache
 ---> 5f7f417804ca
Successfully built 5f7f417804ca
Successfully tagged local/tailwindcss:latest

Done in 110ms.

but ./fails.sh fails with Error: Cannot find module '@tailwindcss/forms':

[19:46]> ./fails.sh 
Sending build context to Docker daemon  73.73kB
Step 1/6 : FROM node:18
 ---> 7e9550136fca
Step 2/6 : RUN mkdir /app /code
 ---> Using cache
 ---> f1794cde37ab
Step 3/6 : COPY tailwind.config.js main.css index.html /code/
 ---> Using cache
 ---> 1684c2b33b98
Step 4/6 : RUN cp /code/tailwind.config.js /app/tailwind.config.js
 ---> Using cache
 ---> d160a106acaa
Step 5/6 : WORKDIR /app
 ---> Using cache
 ---> d8443c56b8bf
Step 6/6 : RUN npm install -D tailwindcss @tailwindcss/forms
 ---> Using cache
 ---> 5f7f417804ca
Successfully built 5f7f417804ca
Successfully tagged local/tailwindcss:latest
node:internal/modules/cjs/loader:956
  const err = new Error(message);
              ^

Error: Cannot find module '@tailwindcss/forms'
Require stack:
- /code/tailwind.config.js
- /app/node_modules/tailwindcss/lib/cli.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:956:15)
    at Module._load (node:internal/modules/cjs/loader:804:27)
    at Module.require (node:internal/modules/cjs/loader:1022:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/code/tailwind.config.js:8:5)
    at Module._compile (node:internal/modules/cjs/loader:1120:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1174:10)
    at Module.load (node:internal/modules/cjs/loader:998:32)
    at Module._load (node:internal/modules/cjs/loader:839:12)
    at Module.require (node:internal/modules/cjs/loader:1022:19) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/code/tailwind.config.js',
    '/app/node_modules/tailwindcss/lib/cli.js'
  ]
}

Node.js v18.6.0
@saites
Copy link
Author

saites commented Jul 24, 2022

The problem seems to be that something (either tailwindcss or this plugin) is trying to resolve the import relative the config file path, rather than the current working directory. Both the works.sh and fails.sh script will succeed if I modify the tailwind.config.js file with an absolute path to the node_modules directory, i.e.,

module.exports = { 
  content: ["/code/**/*.{html,js}"],
  theme: {
    extend: {}, 
  },  
  plugins: [
    require('/app/node_modules/@tailwindcss/forms'),
  ],  
}

@bradlc bradlc self-assigned this Jul 26, 2022
@bradlc
Copy link
Contributor

bradlc commented Jul 26, 2022

Hey @saites. This is just how Node.js module resolution works:

If the module identifier passed to require() is not a core module, and does not begin with '/', '../', or './', then Node.js starts at the directory of the current module, and adds /node_modules, and attempts to load the module from that location. Node.js will not append node_modules to a path already ending in node_modules.

If it is not found there, then it moves to the parent directory, and so on, until the root of the file system is reached.

The key thing here is that when using require() modules are resolved relative to the current module, not the working directory.

Here is your directory structure:

/app/
├─ node_modules/
│  ├─ @tailwindcss/
│  │  ├─ forms/
/code/
├─ index.html
├─ main.css
├─ tailwind.config.js

The require('@tailwindcss/forms') appears in the /code/tailwind.config.js file, which means that Node.js will look in the following directories for that module:

  • /code/node_modules
  • /node_modules

As you can see, neither of these directories exist so resolution fails and you get the error you are seeing.

It's difficult to give specific recommendations without seeing your actual project, but in your minimal reproduction running npm install in the root directory or /code instead of /app would fix the issue. I hope that helps!

@bradlc bradlc closed this as completed Jul 26, 2022
@saites
Copy link
Author

saites commented Jul 26, 2022

Thanks, makes sense. I had a feeling this is a consequence of my unfamiliarity with node. I was thinking of the --config argument as static config, not as an actual script to execute. The resolution makes sense, thinking through what that require must be doing.

My project uses a Rust server to render and serve Handlebars templates, so my only use of Node is to generate this CSS. As a consequence, the example in the repo isn't actually that different from how I'm using the CLI tool -- I'm running it in a Docker container with the relevant directories mounted, and hence, I had the config in a different directory than the original install. I think going forward, I'll probably just bake it into the image.

Thanks again for the help, and the great work with Tailwind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants