webpack-contrib/style-loader

"ReferenceError: document is not defined" when using require() from html file

flipcc opened this issue ยท 10 comments

**Edit: Changed config to browser target in response to this comment. Problem persists.

  • Operating System: Windows10
  • Node Version: v12.14.0
  • NPM Version: 6.13.4
  • webpack Version: 4.41.5
  • style-loader Version: 1.1.3

Expected Behavior

Require the css file from index.html and have webpack -> file-loader -> style-loader inject it into a link tag in the head (see webpack.config.js). Same as when I import the file from index.js.

<!DOCTYPE html>
<html>
  <head>
-    ${require('../style/main.css')}
+    <link rel="stylesheet" href="main.css">
  </head>
  <body></body>
</html>

Actual Behavior

An error is thrown stating that no link tag can be added as document is not defined.

ERROR in   Error: C:\Users\pmueller\Desktop\project/node_modules/style-loader/dist/runtime/injectStylesIntoLinkTag.js?:39
    var link = document.createElement('link');
               ^
  ReferenceError: document is not defined

Code

// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'development',
  entry: './src/scripts/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  devServer: { contentBase: './dist' },
  module: {
    rules: [
      {
        test: /\.html$/i,
        use: [
          {
            loader: 'html-loader',
            options: { interpolate: true }
          }
        ]
      },
      {
        test: /\.css$/i,
        use: [
          {
            loader: 'style-loader',
            options: { injectType: 'linkTag' }
          },
          { loader: 'file-loader' }
        ]
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })]
};
// index.js

/* is empty */
<!-- index.html -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    ${require('../style/main.css')}
    <title>Hello...</title>
  </head>
  <body>
    <div class="some-main-css-class"> ..world.</div>
  </body>
</html>

How Do We Reproduce?

The stated files include everything needed to reproduce the issue raised.

Do not use style-loader and file-loader together, use style-loader for browsers target and file-loader for node target

@evilebottnawi Combination of css-loader and style-loader does also not work. But you are still right in your remark concerning the build target. I updated my issue description and linked to your comment.

The error document is not defined says that your environment is not a browser where document is unavailable. Why you include ${require('../style/main.css')} in html? HtmlWebpackPlugin generated script and link tags by itself, you don't need it

Maybe this is an issue that is connected with html-loader like it is stated in this SO answer or this connected issue.

Your problem is not same

@evilebottnawi Ok, i understand your question. So till now we had a line like import './style/main.css in our every index.js/js entry script. But the line felt never right in this place. So I got the task of moving the import from the index.js/entry script into the head of the index.html file. I constructed the above example case, where index.js/the entry script is clear, but now the error about document being undefined arose. But moving the import from the index.js to the index.html does not change the built environment for my understanding.
I am really willing to understand it, as I really want to implement a solution.

I am really willing to understand it, as I really want to implement a solution.

Can you clarify what do you want? If you need extract styles, please use https://github.com/webpack-contrib/mini-css-extract-plugin.

The template option for the HtmlWebpackPlugin plugin requires interpolate variables on node side, but you use style-loader and it is include browser code for the node environment (${require('../style/main.css')} transforms into the browser code), so you got the error.

Ah ok. Yeah of course require-->node! Thank you so much. Really had a blind spot there.
Have a nice day.

@flipcc could you please explain this comment "require-->node!" I am having a similar issue with my webpack implementation.

With 'blind spot' or 'require--->node' I am referring to the fact, that I wrote import ... , as my mind was still in the web browser. But now with webpack I was working on the server-side/in Node.js. And this means I did have to use require ....

Of course there is a new version of Node.js that supports import/ES Modules, but it is not a LTS version.

Hope this helps.

For me, the error was that I am using "style-loader" in webpack.server.config.js. which is wrong.
"style-loader" should be used in webpack.client.config.js

I got this error when using this beside https://www.npmjs.com/package/mini-css-extract-plugin