css-loader fails to bundle bootstrap.min.css in Server-side rendering, while sass-loader succeeds

Created on 13 Feb 2018  路  10Comments  路  Source: webpack-contrib/css-loader

I'm trying to create a server-side rendering configuration for my React app with Webpack and Express.js and it almost works.

I managed to bundle my .jsx and sass, not using style-loader (which is client-only), but going with ExtractTextPlugin instead.

All was good, but then I tried to include css files into the bundle and on any css file, e.g. bootstrap.min.css, webpack chokes, although my SASS works fine. Here's the error message:

$ node_modules/webpack/bin/webpack.js --config ssr-webpack.config.js

Hash: 3e273674716344c7aa0b
Version: webpack 2.7.0
Time: 7982ms
     Asset     Size  Chunks                    Chunk Names
 server.js  3.82 MB       0  [emitted]  [big]  main
server.css  75.1 kB       0  [emitted]         main
   [4] ./src/services/translate.jsx 1.81 kB {0} [built]
   [6] ./src/pages/Blog.jsx 19.1 kB {0} [built]
   [7] ./src/pages/Post.jsx 10.5 kB {0} [built]
   [8] ./src/pages/Layout.jsx 13 kB {0} [built]
  [22] ./src/pages/Home.jsx 2.96 kB {0} [built]
  [27] ./src/pages/posts/2017-10-21-1/index.jsx 9.71 kB {0} [optional] [built]
  [28] ./src/pages/posts/2017-10-25-1/index.jsx 12.7 kB {0} [optional] [built]
  [29] ./src/pages/posts/2017-11-01-1/index.jsx 21 kB {0} [optional] [built]
  [30] ./src/pages/posts/2017-11-21-1/index.jsx 29.3 kB {0} [optional] [built]
  [31] ./src/pages/posts/2017-11-30-1/index.jsx 24.2 kB {0} [optional] [built]
  [39] ./src/server/app.jsx 4.02 kB {0} [built]
  [41] ./src/pages/Blog.scss 41 bytes {0} [built]
  [42] ./src/pages/Post.scss 41 bytes {0} [built]
  [43] ./src/styles/style.scss 41 bytes {0} [built]
  [57] ./src/pages/posts \.jsx 624 bytes {0} [built]
    + 49 hidden modules
Child extract-text-webpack-plugin:
       [0] ./~/css-loader/lib/css-base.js 2.26 kB {0} [built]
       [1] ./~/css-loader?{"sourceMap":true}!./~/sass-loader/lib/loader.js?{"sourceMap":true}!./src/pages/Post.scss 450 bytes {0} [built]
Child extract-text-webpack-plugin:
       [0] ./~/css-loader/lib/css-base.js 2.26 kB {0} [built]
       [1] ./~/css-loader?{"sourceMap":true}!./~/sass-loader/lib/loader.js?{"sourceMap":true}!./src/pages/Blog.scss 1.16 kB {0} [built]
Child extract-text-webpack-plugin:
       [0] ./~/css-loader/lib/css-base.js 2.26 kB {0} [built]
        + 1 hidden modules
Child extract-text-webpack-plugin:
       [0] ./~/css-loader/lib/css-base.js 2.26 kB {0} [built]
       [1] ./~/css-loader?{"sourceMap":true}!./~/sass-loader/lib/loader.js?{"sourceMap":true}!./src/styles/style.scss 200 kB {0} [built]
/home/burkov/myproject/node_modules/bootstrap/dist/css/bootstrap.min.css:5
 *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:cont
SyntaxError: Unexpected token {
    at Object.exports.runInThisContext (vm.js:73:16)
    at Module._compile (module.js:543:28)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/home/burkov/myproject/dist/server.js:9084:18)
    at __webpack_require__ (/home/burkov/myproject/dist/server.js:20:30)

npm ERR! Linux 4.9.0-5-amd64
npm ERR! argv "/home/burkov/.nvm/versions/node/v7.5.0/bin/node" "/home/burkov/.nvm/versions/node/v7.5.0/bin/npm" "run" "ssr"
npm ERR! node v7.5.0
npm ERR! npm  v4.1.2
npm ERR! code ELIFECYCLE
npm ERR! [email protected] ssr: `node_modules/webpack/bin/webpack.js --config ssr-webpack.config.js && node dist/server.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] ssr script 'node_modules/webpack/bin/webpack.js --config ssr-webpack.config.js && node dist/server.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the burkov package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node_modules/webpack/bin/webpack.js --config ssr-webpack.config.js && node dist/server.js
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs burkov
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls burkov
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /home/burkov/myproject/npm-debug.log

Here is my ssr-webpack.config.js configuration:

module.exports = {
  target: 'node', // ignores built-in modules, creates output for node.js
  externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
  entry: path.resolve(__dirname, 'src', 'server', 'app.jsx'),
  output: {
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/dist/',
    filename: 'server.js'
  },
  resolve: {
    modules: [path.join(__dirname, 'src'), path.join(__dirname, 'node_modules')]
  },
  plugins: [
    new ExtractTextPlugin('server.css')
  ],
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        query: {
          presets: ['es2015', 'react'],
          plugins: ['transform-es2015-destructuring', 'transform-object-rest-spread']
        }
      },
      {
        test: /\.(scss|sass)$/,
        use: ExtractTextPlugin.extract({
          use: [
            { loader: 'css-loader', options: {sourceMap: true} },
            { loader: 'sass-loader', options: {sourceMap: true} }
          ]
        })
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          use: [
            { loader: 'css-loader', options: {sourceMap: true} }
          ]
        })
      },
      {
        test: /\.(png|jpe?g|gif)(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url-loader?emitFile=false'
      },
      {
        test: /\.(eot|com|json|ttf|woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url-loader?emitFile=false'
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'url-loader?emitFile=false'
      }
    ]
  }
};

Versions:
Node.js: 7.5.0
Webpack: ^2.2.0 (apparently, 2.7.0)
css-loader: ^0.28.4
OS: Debian 9

5 (nice to have) Patch 4 (inconvenient) Documentation

Most helpful comment

@evilebottnawi

Hiya! I think, I solved the problem with inclusion of css files into the bundle.

I should have read the webpack-node-externals documentation more carefully. They suggest that you use a regex for whitelisting non-javascript assets served from node_modules, so that they are not excluded from the bundle:

...
nodeExternals({
  // load non-javascript files with extensions, presumably via loaders
  whitelist: [/\.(?!(?:jsx?|json)$).{1,5}$/i],
}),
...

I added it and it works like a charm, although even with explanation I barely understand, how it excludes javascript.

Thanks again for your willingness to help!

All 10 comments

@BurkovBA can you create minimum reproducible test repo?

@evilebottnawi Thanks for reply!

I figured the cause of the problem. It turns out that due to the fact that I'm using nodeExternals:

externals: [nodeExternals()], // in order to ignore all modules in node_modules folder

to avoid inclusion of javascript from node_modules into the bundle, css that also resides in my node_modules (such as bootstrap.min.css) is also excluded and not passed to ExtractTextPlugin, but just required within the bundle with statements like:

/***/ })
/* 59 */
/***/ (function(module, exports) {
module.exports = require("bootstrap/dist/css/bootstrap.min.css");
}

Obviously, bootstrap.min.css is not a javascript code, so when node.js tries to execute this css as javascript, it returns an error on the very first line of css, which is an html { selector:

SyntaxError: Unexpected token {

I'm not sure, how to avoid this problem, though. I can't get rid of nodeExternals, cause without them javascript breaks, but I also need to bundle css from node_modules.

@BurkovBA very strange, maybe problem in webpack, tomorrow i will investigate this, also minimum reproducible test repo will help me to do this faster.

@evilebottnawi It's not exactly minimal, but this code is a part of my personal blog's repo: https://github.com/BurkovBA/BurkovBA.github.io

Take a look into package.json. It contains ssr script for building server-side, so you can run npm run ssr to reproduce the bug.

ssr-webpack.config.js in the repo's root is used for building Server-Side Rendered bundle and put it into /dist folder of the repo.

The server's code is in /src/server folder.

Thanks for your help, @evilebottnawi! If anything in my codebase is unclear, don't hesitate to ask me.

@evilebottnawi

Hiya! I think, I solved the problem with inclusion of css files into the bundle.

I should have read the webpack-node-externals documentation more carefully. They suggest that you use a regex for whitelisting non-javascript assets served from node_modules, so that they are not excluded from the bundle:

...
nodeExternals({
  // load non-javascript files with extensions, presumably via loaders
  whitelist: [/\.(?!(?:jsx?|json)$).{1,5}$/i],
}),
...

I added it and it works like a charm, although even with explanation I barely understand, how it excludes javascript.

Thanks again for your willingness to help!

@BurkovBA Great! Can you create improve docs (PR)?

Hi, @evilebottnawi!

Sure, I will do a PR.

Should I add an example of my configuration of Server-Side Rendering with CSS-loader to https://github.com/webpack-contrib/css-loader#examples section of README.md and explain in details what line does what?

@BurkovBA Will be great!

@evilebottnawi

Sent the PR with a detailed description of setup and example webpack configuration relevant to css-loader.

Cheers!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tapz picture tapz  路  3Comments

grydstedt picture grydstedt  路  3Comments

cuiyue picture cuiyue  路  3Comments

dmiller9911 picture dmiller9911  路  3Comments

kcjonson picture kcjonson  路  3Comments