jaredpalmer / razzle

✨ Create server-rendered universal JavaScript applications with no configuration
https://razzlejs.org
MIT License
11.1k stars 866 forks source link

With Razzle 4, I can't just use Webpack 5 #1662

Open heath-freenome opened 3 years ago

heath-freenome commented 3 years ago

🐛 Bug report

Current Behavior

According to the documentation I can just pick webpack 5 and things will work... only when I do razzle build produces a TON of errors when I turn on debug: { compile: true } and my code fails to run.

I'm guessing that I need to update a lot more than just the two packages indicated (webpack@5.24.0 html-webpack-plugin@5.2.0). First when running the command, I see the following warnings:

(node:7556) [DEP_WEBPACK_COMPILATION_OPTIMIZE_CHUNK_ASSETS] DeprecationWarning: optimizeChunkAssets is deprecated (use Compilation.hooks.processAssets instead and use one of Compilation.PROCESS_ASSETS_STAGE_* as stage option)
(Use `node --trace-deprecation ...` to show where the warning was created)
Using external babel configuration from /Users/heath/dev/hermes-ui/.babelrc for "web" build
(node:7556) [DEP_WEBPACK_COMPILATION_CACHE] DeprecationWarning: Compilation.cache was removed in favor of Compilation.getCache()

I see resolve problems like (webpack can be configured to avoid this as noted in this documentation fix):

  {
    moduleIdentifier: '/Users/heath/dev/hermes-ui/node_modules/@babel/runtime/helpers/esm/inherits.js',
    moduleName: './node_modules/@babel/runtime/helpers/esm/inherits.js',
    loc: '1:0-46',
    message: "Module not found: Error: Can't resolve './setPrototypeOf' in '/Users/heath/dev/hermes-ui/node_modules/@babel/runtime/helpers/esm'\n" +
      "Did you mean 'setPrototypeOf.js'?\n" +
      "BREAKING CHANGE: The request './setPrototypeOf' failed to resolve only because it was resolved as fully specified\n" +
      `(probably because the origin is a '*.mjs' file or a '*.js' file where the package.json contains '"type": "module"').\n` +
      'The extension in the request is mandatory for it to be fully specified.\n' +
      'Add the extension to the request.',
    moduleId: null,
    moduleTrace: [
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object]
    ],
    details: "resolve './setPrototypeOf' in '/Users/heath/dev/hermes-ui/node_modules/@babel/runtime/helpers/esm'\n" +
      '  using description file: /Users/heath/dev/hermes-ui/node_modules/@babel/runtime/helpers/esm/package.json (relative path: .)\n' +
      "    Field 'browser' doesn't contain a valid alias configuration\n" +
      '    using description file: /Users/heath/dev/hermes-ui/node_modules/@babel/runtime/helpers/esm/package.json (relative path: ./setPrototypeOf)\n' +
      "      Field 'browser' doesn't contain a valid alias configuration\n" +
      "      /Users/heath/dev/hermes-ui/node_modules/@babel/runtime/helpers/esm/setPrototypeOf doesn't exist",
    stack: "ModuleNotFoundError: Module not found: Error: Can't resolve './setPrototypeOf' in '/Users/heath/dev/hermes-ui/node_modules/@babel/runtime/helpers/esm'\n" +
      "Did you mean 'setPrototypeOf.js'?\n" +
      "BREAKING CHANGE: The request './setPrototypeOf' failed to resolve only because it was resolved as fully specified\n" +
      `(probably because the origin is a '*.mjs' file or a '*.js' file where the package.json contains '"type": "module"').\n` +
      'The extension in the request is mandatory for it to be fully specified.\n' +
      'Add the extension to the request.\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/Compilation.js:1771:28\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:742:13\n' +
      '    at eval (eval at create (/Users/heath/dev/hermes-ui/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:10:1)\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:276:22\n' +
      '    at eval (eval at create (/Users/heath/dev/hermes-ui/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:405:22\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:119:11\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:650:24\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:813:8\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:933:5\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/neo-async/async.js:6883:13\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:850:17\n' +
      '    at finishResolved (/Users/heath/dev/hermes-ui/node_modules/enhanced-resolve/lib/Resolver.js:278:11)\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/enhanced-resolve/lib/Resolver.js:342:25\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/enhanced-resolve/lib/Resolver.js:409:24\n' +
      '    at eval (eval at create (/Users/heath/dev/hermes-ui/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:1:1), <anonymous>:12:1)'
  },

I also see errors from terser.js like the following (Webpack 5 comes with it out-of-the-box) so it can be removed from the optimizations.minimizer array):

  {
    message: 'static/js/client.55e2a441.js from Terser\n' +
      'RangeError: Invalid string length\n' +
      '    at String.replace (<anonymous>)\n' +
      '    at serialize (/Users/heath/dev/hermes-ui/node_modules/serialize-javascript/index.js:207:16)\n' +
      '    at TaskRunner.runTask (/Users/heath/dev/hermes-ui/node_modules/razzle/node_modules/terser-webpack-plugin/dist/TaskRunner.js:41:69)\n' +
      '    at enqueue (/Users/heath/dev/hermes-ui/node_modules/razzle/node_modules/terser-webpack-plugin/dist/TaskRunner.js:89:35)\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/razzle/node_modules/terser-webpack-plugin/dist/TaskRunner.js:113:86\n' +
      '    at processTicksAndRejections (internal/process/task_queues.js:93:5)',
    details: undefined,
    stack: 'Error: static/js/client.55e2a441.js from Terser\n' +
      'RangeError: Invalid string length\n' +
      '    at String.replace (<anonymous>)\n' +
      '    at serialize (/Users/heath/dev/hermes-ui/node_modules/serialize-javascript/index.js:207:16)\n' +
      '    at TaskRunner.runTask (/Users/heath/dev/hermes-ui/node_modules/razzle/node_modules/terser-webpack-plugin/dist/TaskRunner.js:41:69)\n' +
      '    at enqueue (/Users/heath/dev/hermes-ui/node_modules/razzle/node_modules/terser-webpack-plugin/dist/TaskRunner.js:89:35)\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/razzle/node_modules/terser-webpack-plugin/dist/TaskRunner.js:113:86\n' +
      '    at processTicksAndRejections (internal/process/task_queues.js:93:5)\n' +
      '    at Function.buildError (/Users/heath/dev/hermes-ui/node_modules/razzle/node_modules/terser-webpack-plugin/dist/index.js:98:14)\n' +
      '    at Object.callback (/Users/heath/dev/hermes-ui/node_modules/razzle/node_modules/terser-webpack-plugin/dist/index.js:241:48)\n' +
      '    at enqueue (/Users/heath/dev/hermes-ui/node_modules/razzle/node_modules/terser-webpack-plugin/dist/TaskRunner.js:100:14)\n' +
      '    at processTicksAndRejections (internal/process/task_queues.js:93:5)'
  }

And also errors like this (which can be fixed using the node-polyfill-webpack-plugin):

  {
    moduleIdentifier: '/Users/heath/dev/hermes-ui/node_modules/htmlparser2/lib/WritableStream.js',
    moduleName: './node_modules/htmlparser2/lib/WritableStream.js',
    loc: '6:13-37',
    message: "Module not found: Error: Can't resolve 'buffer' in '/Users/heath/dev/hermes-ui/node_modules/htmlparser2/lib'\n" +
      '\n' +
      'BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.\n' +
      'This is no longer the case. Verify if you need this module and configure a polyfill for it.\n' +
      '\n' +
      'If you want to include a polyfill, you need to:\n' +
      `\t- add a fallback 'resolve.fallback: { "buffer": require.resolve("buffer/") }'\n` +
      "\t- install 'buffer'\n" +
      "If you don't want to include a polyfill, you can use an empty module like this:\n" +
      '\tresolve.fallback: { "buffer": false }',
    moduleId: 83621,
    moduleTrace: [
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object]
    ],
    details: "resolve 'buffer' in '/Users/heath/dev/hermes-ui/node_modules/htmlparser2/lib'\n" +
      '  Parsed request is a module\n' +
      '  using description file: /Users/heath/dev/hermes-ui/node_modules/htmlparser2/package.json (relative path: ./lib)\n' +
      '    resolve as module\n' +
      '      looking for modules in /Users/heath/dev/hermes-ui/src\n' +
      '        single file module\n' +
      '          using description file: /Users/heath/dev/hermes-ui/package.json (relative path: ./src/buffer)\n' +
      '            no extension\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/src/buffer doesn't exist\n" +
      '            .mjs\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/src/buffer.mjs doesn't exist\n" +
      '            .js\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/src/buffer.js doesn't exist\n" +
      '            .jsx\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/src/buffer.jsx doesn't exist\n" +
      '            .json\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/src/buffer.json doesn't exist\n" +
      '            .ts\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/src/buffer.ts doesn't exist\n" +
      '            .tsx\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/src/buffer.tsx doesn't exist\n" +
      '            .svg\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/src/buffer.svg doesn't exist\n" +
      "        /Users/heath/dev/hermes-ui/src/buffer doesn't exist\n" +
      "      /Users/heath/dev/hermes-ui/node_modules/htmlparser2/lib/node_modules doesn't exist or is not a directory\n" +
      '      looking for modules in /Users/heath/dev/hermes-ui/node_modules/htmlparser2/node_modules\n' +
      '        single file module\n' +
      '          using description file: /Users/heath/dev/hermes-ui/node_modules/htmlparser2/package.json (relative path: ./node_modules/buffer)\n' +
      '            no extension\n' +
      "              /Users/heath/dev/hermes-ui/node_modules/htmlparser2/node_modules/buffer doesn't exist\n" +
      '            .mjs\n' +
      "              /Users/heath/dev/hermes-ui/node_modules/htmlparser2/node_modules/buffer.mjs doesn't exist\n" +
      '            .js\n' +
      "              /Users/heath/dev/hermes-ui/node_modules/htmlparser2/node_modules/buffer.js doesn't exist\n" +
      '            .jsx\n' +
      "              /Users/heath/dev/hermes-ui/node_modules/htmlparser2/node_modules/buffer.jsx doesn't exist\n" +
      '            .json\n' +
      "              /Users/heath/dev/hermes-ui/node_modules/htmlparser2/node_modules/buffer.json doesn't exist\n" +
      '            .ts\n' +
      "              /Users/heath/dev/hermes-ui/node_modules/htmlparser2/node_modules/buffer.ts doesn't exist\n" +
      '            .tsx\n' +
      "              /Users/heath/dev/hermes-ui/node_modules/htmlparser2/node_modules/buffer.tsx doesn't exist\n" +
      '            .svg\n' +
      "              /Users/heath/dev/hermes-ui/node_modules/htmlparser2/node_modules/buffer.svg doesn't exist\n" +
      "        /Users/heath/dev/hermes-ui/node_modules/htmlparser2/node_modules/buffer doesn't exist\n" +
      "      /Users/heath/dev/hermes-ui/node_modules/node_modules doesn't exist or is not a directory\n" +
      '      looking for modules in /Users/heath/dev/hermes-ui/node_modules\n' +
      '        single file module\n' +
      '          using description file: /Users/heath/dev/hermes-ui/package.json (relative path: ./node_modules/buffer)\n' +
      '            no extension\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer doesn't exist\n" +
      '            .mjs\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.mjs doesn't exist\n" +
      '            .js\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.js doesn't exist\n" +
      '            .jsx\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.jsx doesn't exist\n" +
      '            .json\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.json doesn't exist\n" +
      '            .ts\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.ts doesn't exist\n" +
      '            .tsx\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.tsx doesn't exist\n" +
      '            .svg\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.svg doesn't exist\n" +
      "        /Users/heath/dev/hermes-ui/node_modules/buffer doesn't exist\n" +
      "      /Users/heath/dev/node_modules doesn't exist or is not a directory\n" +
      "      /Users/heath/node_modules doesn't exist or is not a directory\n" +
      "      /Users/node_modules doesn't exist or is not a directory\n" +
      "      /node_modules doesn't exist or is not a directory\n" +
      '      looking for modules in /Users/heath/dev/hermes-ui/node_modules\n' +
      '        single file module\n' +
      '          using description file: /Users/heath/dev/hermes-ui/package.json (relative path: ./node_modules/buffer)\n' +
      '            no extension\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer doesn't exist\n" +
      '            .mjs\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.mjs doesn't exist\n" +
      '            .js\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.js doesn't exist\n" +
      '            .jsx\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.jsx doesn't exist\n" +
      '            .json\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.json doesn't exist\n" +
      '            .ts\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.ts doesn't exist\n" +
      '            .tsx\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.tsx doesn't exist\n" +
      '            .svg\n' +
      "              Field 'browser' doesn't contain a valid alias configuration\n" +
      "              /Users/heath/dev/hermes-ui/node_modules/buffer.svg doesn't exist\n" +
      "        /Users/heath/dev/hermes-ui/node_modules/buffer doesn't exist",
    stack: "ModuleNotFoundError: Module not found: Error: Can't resolve 'buffer' in '/Users/heath/dev/hermes-ui/node_modules/htmlparser2/lib'\n" +
      '\n' +
      'BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.\n' +
      'This is no longer the case. Verify if you need this module and configure a polyfill for it.\n' +
      '\n' +
      'If you want to include a polyfill, you need to:\n' +
      `\t- add a fallback 'resolve.fallback: { "buffer": require.resolve("buffer/") }'\n` +
      "\t- install 'buffer'\n" +
      "If you don't want to include a polyfill, you can use an empty module like this:\n" +
      '\tresolve.fallback: { "buffer": false }\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/Compilation.js:1771:28\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:742:13\n' +
      '    at eval (eval at create (/Users/heath/dev/hermes-ui/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:10:1)\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:276:22\n' +
      '    at eval (eval at create (/Users/heath/dev/hermes-ui/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:405:22\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:119:11\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:650:24\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:813:8\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:933:5\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/neo-async/async.js:6883:13\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/webpack/lib/NormalModuleFactory.js:916:45\n' +
      '    at finishWithoutResolve (/Users/heath/dev/hermes-ui/node_modules/enhanced-resolve/lib/Resolver.js:296:11)\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/enhanced-resolve/lib/Resolver.js:362:15\n' +
      '    at /Users/heath/dev/hermes-ui/node_modules/enhanced-resolve/lib/Resolver.js:410:5\n' +
      '    at eval (eval at create (/Users/heath/dev/hermes-ui/node_modules/enhanced-resolve/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)'
  },

Expected behavior

I follow the directions for using webpack 5 and it works

Reproducible example

Suggested solution(s)

Here's how I worked around them in my custom razzle.config.js

First the resolve issue:

    // Insert the rule to disable webpack 5 default resolve behavior
    newWebpackConfig.module.rules.unshift({
      test: /\.m?js/,
      resolve: {
        fullySpecified: false // disable the behaviour
      }
    });

Second the Terser issue:

    if (newWebpackConfig.optimization && newWebpackConfig.optimization.minimizer) {
      // Webpack 5 comes with the TerserPlugin out of the box, so remove it from the optimization.minimizer in the configuration
      const terserIndex = newWebpackConfig.optimization.minimizer.findIndex((item) => item.constructor.name === 'TerserPlugin');
      newWebpackConfig.optimization.minimizer.splice(terserIndex, 1);
    }

Third the polyfill issue:

UPDATE: The following original solution broke my apps ability to get process environment variables because too much was polyfilled...

// DO NOT USE
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin")
...
    // Add the node polyfill plugin for webpack 5
    newWebpackConfig.plugins.push(new NodePolyfillPlugin());

INSTEAD, I went with the solution actually spelled out in the error message (doh):

newWebpackConfig.resolve = {
   ...newWebpackConfig.resolve,
   fallback: { buffer: require.resolve('buffer/') },
};

This required me to npm install buffer instead of the node-polyfill-webpack-plugin

Additional context

Even just running the npm version of the command documented tells me something is wrong given the number warnings related to webpack:

 npm install --save-dev webpack@5.24.0 html-webpack-plugin@5.2.0
npm WARN @vue/compiler-sfc@3.1.4 requires a peer of vue@3.1.4 but none is installed. You must install peer dependencies yourself.
npm WARN jest-environment-jsdom-global@2.0.4 requires a peer of jest-environment-jsdom@22.x || 23.x || 24.x || 25.x || 26.x but none is installed. You must install peer dependencies yourself.
npm WARN razzle@4.0.5 requires a peer of mini-css-extract-plugin@^0.9.0 but none is installed. You must install peer dependencies yourself.
npm WARN file-loader@4.3.0 requires a peer of webpack@^4.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN url-loader@2.3.0 requires a peer of webpack@^4.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN webpackbar@4.0.0 requires a peer of webpack@^3.0.0 || ^4.0.0 but none is installed. You must install peer dependencies yourself.

+ html-webpack-plugin@5.2.0
+ webpack@5.24.0
added 27 packages from 21 contributors, removed 110 packages, updated 26 packages and moved 2 packages in 15.788s

194 packages are looking for funding
  run `npm fund` for details

Your environment

Software Version(s)
Razzle 4.0.5
Razzle Plugins 4.0.5
Node 14.16.0
Browser n/a
npm/Yarn npm 6.14.11
Operating System macOs
TypeScript 4
React 16
fivethreeo commented 3 years ago

Npm 7? Because razzle does not support that yet. Need to split razzle into a wp4 and wp5 version first since npm 7 has stricter deps.

heath-freenome commented 3 years ago

Npm 7? Because razzle does not support that yet. Need to split razzle into a wp4 and wp5 version first since npm 7 has stricter deps.

No, 6.14.11 I kind of figured out how to work around all of those issues as I've mentioned above although I'm still seeing one deprecation warning:

(node:16842) [DEP_WEBPACK_EXTERNALS_FUNCTION_PARAMETERS] DeprecationWarning: The externals-function should be defined like ({context, request}, cb) => { ... }

And I'm guessing it probably makes sense to make the file-loader, url-loader and webpackbar be peer-deps so that razzle doesn't lock them down to webpack 4 versions

EvanCoh commented 3 years ago

Thank you @heath-freenome , I had to apply the very same changes like you described them, to solve the issues. lifesaver!