linaria icon indicating copy to clipboard operation
linaria copied to clipboard

webpack errors after update to 3.0.0-beta.16

Open kryops opened this issue 3 years ago • 13 comments

Environment

  • Linaria version: 3.0.0-beta.16
  • Bundler (+ version): webpack 5.65.0
  • Node.js version: 17.2.0
  • OS: Linux

Description

Hi there,

after upgrading to 3.0.0-beta.16, there are some errors in my webpack build that I cannot quite figure out on my own.

The first error is

Conflict: Multiple chunks emit assets to the same filename styles.css (chunks 179 and 532)

This seems to be related to my optimization.splitChunks.cacheGroups option that I have configured to include the CSS for lazy-loaded chunks into the main CSS chunk:

styles: {
  name: 'styles',
  idHint: 'styles',
  test: /\.css$/,
  chunks: 'all',
  enforce: true,
}

If I comment that out, the actual webpack build seems to work fine again (and there is only one CSS chunk, so I'm not sure if that option is even still necessary) - but then I run into errors when starting webpack-dev-server (using React Fast Refresh):

ERROR in ./src/ui/main/main-container.tsx (./src/ui/main/main-container.linaria.css!=!../node_modules/@linaria/webpack5-loader/lib/outputCssLoader.js!./src/ui/main/main-container.tsx)
Module build failed (from ../node_modules/mini-css-extract-plugin/dist/loader.js):
HookWebpackError: Cannot read properties of undefined (reading 'exports')
    at tryRunOrWebpackError (/home/michael/git/remote-mixer/node_modules/webpack/lib/HookWebpackError.js:88:9)
    at __webpack_require_module__ (/home/michael/git/remote-mixer/node_modules/webpack/lib/Compilation.js:4979:12)
    at __webpack_require__ (/home/michael/git/remote-mixer/node_modules/webpack/lib/Compilation.js:4936:18)
    at /home/michael/git/remote-mixer/node_modules/webpack/lib/Compilation.js:5007:20
    at symbolIterator (/home/michael/git/remote-mixer/node_modules/neo-async/async.js:3485:9)
    at done (/home/michael/git/remote-mixer/node_modules/neo-async/async.js:3527:9)
    at Hook.eval [as callAsync] (eval at create (/home/michael/git/remote-mixer/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
    at /home/michael/git/remote-mixer/node_modules/webpack/lib/Compilation.js:4914:43
    at symbolIterator (/home/michael/git/remote-mixer/node_modules/neo-async/async.js:3482:9)
    at timesSync (/home/michael/git/remote-mixer/node_modules/neo-async/async.js:2297:7)
-- inner error --
TypeError: Cannot read properties of undefined (reading 'exports')
    at Object.getModuleExports (/home/michael/git/remote-mixer/node_modules/@pmmmwh/react-refresh-webpack-plugin/lib/runtime/RefreshUtils.js:10:58)
    at Module.<anonymous> (/home/michael/git/remote-mixer/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[1].use[1]!/home/michael/git/remote-mixer/node_modules/@linaria/webpack5-loader/lib/outputCssLoader.js!/home/michael/git/remote-mixer/frontend/src/ui/main/main-container.tsx:23:62)
    at /home/michael/git/remote-mixer/node_modules/webpack/lib/javascript/JavascriptModulesPlugin.js:432:11
    at Hook.eval (eval at create (/home/michael/git/remote-mixer/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:7:1)
    at /home/michael/git/remote-mixer/node_modules/webpack/lib/Compilation.js:4981:39
    at tryRunOrWebpackError (/home/michael/git/remote-mixer/node_modules/webpack/lib/HookWebpackError.js:83:7)
    at __webpack_require_module__ (/home/michael/git/remote-mixer/node_modules/webpack/lib/Compilation.js:4979:12)
    at __webpack_require__ (/home/michael/git/remote-mixer/node_modules/webpack/lib/Compilation.js:4936:18)
    at /home/michael/git/remote-mixer/node_modules/webpack/lib/Compilation.js:5007:20
    at symbolIterator (/home/michael/git/remote-mixer/node_modules/neo-async/async.js:3485:9)

Reproducible Demo

I have created a branch in my remote-mixer project: https://github.com/kryops/remote-mixer/tree/linaria3-beta16-error (Edit: Now with 2 commits on top to fix the issues)

Going back one commit shows that 3.0.0-beta.15 does not seem to be affected.

You can use the following commands to reproduce the problems:

  • yarn to install the dependencies
  • yarn frontend build runs a normal webpack build (you can verify that the result is ok by running yarn build and then yarn start:prod)
  • yarn start starts the dev server

Thanks for looking into it!

kryops avatar Dec 19 '21 10:12 kryops

We are also seeing this in [email protected]:

ERROR in ../button/src/styles.js (/path/to/project/node_modules/@storybook/react/node_modules/css-loader/dist/cjs.js??ref--7-1!/path/to/project/node_modules/postcss-loader/src??postcss!/path/to/project/node_modules/linaria/lib/outputCssLoader.js?cacheProvider=undefined!../button/src/styles.js)
Module build failed (from /path/to/project/node_modules/linaria/lib/outputCssLoader.js):
Error: Cannot find module 'undefined'
Require stack:
- /path/to/project/node_modules/linaria/lib/cache.js
- /path/to/project/node_modules/linaria/lib/loader.js
- /path/to/project/node_modules/linaria/loader.js
- /path/to/project/node_modules/loader-runner/lib/loadLoader.js
- /path/to/project/node_modules/loader-runner/lib/LoaderRunner.js
- /path/to/project/node_modules/webpack/lib/NormalModule.js
- /path/to/project/node_modules/webpack/lib/NormalModuleFactory.js
- /path/to/project/node_modules/webpack/lib/Compiler.js
- /path/to/project/node_modules/webpack/lib/webpack.js
- /path/to/project/node_modules/@storybook/react/node_modules/@storybook/core/dist/server/build-static.js
- /path/to/project/node_modules/@storybook/react/node_modules/@storybook/core/server.js
- /path/to/project/node_modules/@storybook/react/dist/server/index.js
- /path/to/project/node_modules/@storybook/react/bin/index.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:885:15)
    at Function.Module._load (internal/modules/cjs/loader.js:730:27)
    at Module.require (internal/modules/cjs/loader.js:957:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at getCacheInstance (/path/to/project/node_modules/linaria/lib/cache.js:44:12)
    at Object.outputCssLoader (/path/to/project/node_modules/linaria/lib/outputCssLoader.js:19:31)
 @ ../button/src/styles.js (../button/src/styles.linaria.css = /path/to/project/node_modules/linaria/lib/outputCssLoader.js?cacheProvider=undefined!../button/src/styles.js) 2:14-268 21:1-42:3 22:19-273
 @ ../button/src/styles.js
 @ ./examples/.setup/uxcore2.js
 @ ./examples/dismissible.js
 @ ./examples sync nonrecursive ^\.\/([-\w]+)\.js$
 @ /path/to/project/node_modules/@exemplar/storybook-react/load-examples.js
 @ multi /path/to/project/node_modules/@storybook/react/node_modules/@storybook/core/dist/server/common/polyfills.js /path/to/project/node_modules/@storybook/react/node_modules/@storybook/core/dist/server/preview/globals.js /path/to/project/node_modules/@exemplar/storybook-react/load-examples.js (webpack)-hot-middleware/client.js?reload=true&quiet=true

We believe this regression is due to #884. We are going to triple-check and confirm that rolling back to and pinning [email protected] fixes this issue.

dcousineau-godaddy avatar Dec 20 '21 16:12 dcousineau-godaddy

I'm having the same issue.. seems to be related to the integration between linaria and pmmmwh/react-refresh-webpack-plugin when removing the fast-refresh plugin things go back to normal...

I can also confirm that rolling back on @linaria/webpack5-loader partially fixed the bug for me.. no errors, but I'm still trying to get react-refresh to function correctly (could be unrelated)

iMoses-Apiiro avatar Dec 20 '21 16:12 iMoses-Apiiro

@kryops I'v reviewed your repo and got the following conclusion:

  1. The `Cannot find module 'undefined' error should be fixed in https://github.com/callstack/linaria/pull/890 and is waiting to be released.

  2. You should use [name].css for the filename of mini-css-extract-plugin, although you may want to extra all CSS into one file, the output filename should be determined by cacheGroups.

       new ExtractCssPlugin({
         ignoreOrder: true,
-        filename: 'styles.css',
+        filename: '[name].css',
       }),

By changing that line, there should be two CSS file been generated to frontend/dist folder. And if you force them to style.css, a conflict error thrown.

image

  1. So what if you do want to use one CSS file in dist folder ? You can use the type field of cacheGroups.
        cacheGroups: {
           styles: {
             name: 'styles',
             idHint: 'styles',
-            test: /\.css$/,
+            type: 'css/mini-extract',
             chunks: 'all',
             enforce: true,
           }
        }
  1. The root cause of this issue, is when Linaria changed to use inline match resource after #879 , the .linaria.css became a virtual module, its module.nameForCondition() which is used by SplitChunksPlugin also changed from path/to/xxx.linaria.css to path/to/xxx.tsx. The test: /\.css$/ cannot match these CSS files anymore.

In conclusion, this issue happened because of an outdate Webpack config and a bug in latest Linaria v2/v3 https://github.com/callstack/linaria/pull/890

cc @Anber

malash avatar Dec 22 '21 04:12 malash

In conclusion, this issue happened because of an outdate Webpack config and a bug in latest Linaria v2/v3 #890

Ironically #879 is not being released because of this bug, which is simply reporting #879.

IMHO bugs from an existing release should not be cause to block releasing fixes for current release. Only bugs from unreleased code should block new releases.

ntucker avatar Dec 22 '21 04:12 ntucker

@malash thanks so much for your analysis! I must have missed the changed recommendations for mini-css-extract-plugin when upgrading :flushed:

I don't think my undefined issue can be related to #890, as the cacheProvider that caused the issue has only been released for v2 so far.

According to the stack trace, the error surfaces in https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/lib/runtime/RefreshUtils.js#L9, where moduleId is undefined - but I do not quite understand where it is coming from.

Just adding something like if (!moduleId) return {} there seems to fix the problem, and hot reloading still works.

Apparently someone just had the same idea today in react-refresh-webpack-plugin After upgrading the plugin to 0.5.4, I now just get a lot of warnings like [React Refresh] Failed to get exports for module: undefined.

Not sure if that can be improved on Linaria's side, but for now my setup seems to be working again :sweat_smile:

(I updated my reproduction branch so now it works, but shows the warnings in development)

kryops avatar Dec 22 '21 06:12 kryops

@kryops The bug fix of https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/546 did works, but it's not perfect. Many 3rd-party libraries may use variable module, like css-loader uses module.id even if esModule was true.

So I think it is still a bug in react-refresh-webpack-plugin, but not Linaria.

malash avatar Dec 22 '21 10:12 malash

I'm trying to figure out, what is happening inside webpack, css-loader and hmr plugins in order to find a way to prevent this warnings. It seems like a bug that virtual modules don't have moduleId and I have a feeling that this is a Linaria bug.

Anber avatar Dec 22 '21 11:12 Anber

Webpack doesn't pass the second argument (which is a module id) to webpack_require_module for runtime modules https://github.com/webpack/webpack/blob/main/lib/Compilation.js#L5044, so that it is a bug in react-refresh-webpack-plugin which explicitly required moduleId. I can't say if this bug affects HMR for styles but if it's not, warnings can be prevented by excluding those virtual modules from processing with react-refresh-webpack-plugin, but it looks like its exclude options can only handle files and doesn't work with virtual modules. So… I need a decision from the community: shall we keep it as it is now and publish 3.0 release with BC or revert changes in the cache system?

Anber avatar Dec 23 '21 11:12 Anber

I vote publish. Let other libraries fix their issues

ntucker avatar Dec 23 '21 11:12 ntucker

I did a bit more testing, and for me it looks like HMR+React Fast Refresh is indeed working perfectly with Linaria v3 - so I have nothing against it being published 🙂

I commented on https://github.com/pmmmwh/react-refresh-webpack-plugin/issues/245 to see if moduleId === undefined is a special case that can maybe just be ignored silently instead of logging a warning.

kryops avatar Dec 23 '21 17:12 kryops

Regarding [React Refresh] Failed to get exports for module: undefined. - this is fundamentally limited to react-refresh injecting itself into virtual modules like the following:

{
  layer: null,
  request: '/home/ntucker/src/anansi/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[6].oneOf[1].use[1]!/home/ntucker/src/anansi/node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[6].oneOf[1].use[2]!/home/ntucker/src/anansi/node_modules/@linaria/webpack5-loader/lib/outputCssLoader.js?cacheProvider=%2Fhome%2Fntucker%2Fsrc%2Fanansi%2Fpackages%2Fwebpack-config-anansi%2Flib%2Fbase%2FlinariaFileCache.js!/home/ntucker/src/anansi/examples/linaria/src/App.tsx',
  userRequest: '/home/ntucker/src/anansi/examples/linaria/src/App.tsx.webpack[javascript/auto]!=!/home/ntucker/src/anansi/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[6].oneOf[1].use[1]!/home/ntucker/src/anansi/node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[6].oneOf[1].use[2]!/home/ntucker/src/anansi/node_modules/@linaria/webpack5-loader/lib/outputCssLoader.js?cacheProvider=%2Fhome%2Fntucker%2Fsrc%2Fanansi%2Fpackages%2Fwebpack-config-anansi%2Flib%2Fbase%2FlinariaFileCache.js!/home/ntucker/src/anansi/examples/linaria/src/App.tsx',
  rawRequest: '/home/ntucker/src/anansi/examples/linaria/src/App.tsx.webpack[javascript/auto]!=!!!/home/ntucker/src/anansi/node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[6].oneOf[1].use[1]!/home/ntucker/src/anansi/node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[6].oneOf[1].use[2]!/home/ntucker/src/anansi/node_modules/@linaria/webpack5-loader/lib/outputCssLoader.js?cacheProvider=%2Fhome%2Fntucker%2Fsrc%2Fanansi%2Fpackages%2Fwebpack-config-anansi%2Flib%2Fbase%2FlinariaFileCache.js!/home/ntucker/src/anansi/examples/linaria/src/App.tsx',
  loaders: [
    {
      loader: '/home/ntucker/src/anansi/node_modules/css-loader/dist/cjs.js',
      options: [Object],
      ident: 'ruleSet[1].rules[6].oneOf[1].use[1]'
    },
    {
      loader: '/home/ntucker/src/anansi/node_modules/postcss-loader/dist/cjs.js',
      options: [Object],
      ident: 'ruleSet[1].rules[6].oneOf[1].use[2]'
    },
    {
      loader: '/home/ntucker/src/anansi/node_modules/@linaria/webpack5-loader/lib/outputCssLoader.js',
      options: 'cacheProvider=%2Fhome%2Fntucker%2Fsrc%2Fanansi%2Fpackages%2Fwebpack-config-anansi%2Flib%2Fbase%2FlinariaFileCache.js',
      ident: undefined
    }
  ],
  resource: '/home/ntucker/src/anansi/examples/linaria/src/App.tsx',
  context: '/home/ntucker/src/anansi/examples/linaria/src',
  matchResource: '/home/ntucker/src/anansi/examples/linaria/src/App.tsx',
  resourceResolveData: {
    _ResolverCachePluginCacheMiss: true,
    context: {
      issuer: '/home/ntucker/src/anansi/examples/linaria/src/App.linaria.css',
      issuerLayer: undefined,
      compiler: undefined
    },
    path: '/home/ntucker/src/anansi/examples/linaria/src/App.tsx',
    request: undefined,
    query: '',
    fragment: '',
    module: false,
    directory: false,
    file: false,
    internal: false,
    fullySpecified: false,
    descriptionFilePath: '/home/ntucker/src/anansi/examples/linaria/package.json',
    descriptionFileData: {
      name: 'example-linaria',
      version: '3.0.21',
      private: true,
      scripts: [Object],
      devDependencies: [Object],
      dependencies: [Object],
      browserslist: [Array]
    },
    descriptionFileRoot: '/home/ntucker/src/anansi/examples/linaria',
    relativePath: './src/App.tsx',
    __innerRequest_request: undefined,
    __innerRequest_relativePath: './src/App.tsx',
    __innerRequest: './src/App.tsx'
  },
  settings: { type: 'javascript/auto' },
  type: 'javascript/auto',
  parser: JavascriptParser {
    hooks: {
      evaluateTypeof: [HookMap],
      evaluate: [HookMap],
      evaluateIdentifier: [HookMap],
      evaluateDefinedIdentifier: [HookMap],
      evaluateCallExpressionMember: [HookMap],
      isPure: [HookMap],
      preStatement: [Hook],
      blockPreStatement: [Hook],
      statement: [Hook],
      statementIf: [Hook],
      classExtendsExpression: [Hook],
      classBodyElement: [Hook],
      classBodyValue: [Hook],
      label: [HookMap],
      import: [Hook],
      importSpecifier: [Hook],
      export: [Hook],
      exportImport: [Hook],
      exportDeclaration: [Hook],
      exportExpression: [Hook],
      exportSpecifier: [Hook],
      exportImportSpecifier: [Hook],
      preDeclarator: [Hook],
      declarator: [Hook],
      varDeclaration: [HookMap],
      varDeclarationLet: [HookMap],
      varDeclarationConst: [HookMap],
      varDeclarationVar: [HookMap],
      pattern: [HookMap],
      canRename: [HookMap],
      rename: [HookMap],
      assign: [HookMap],
      assignMemberChain: [HookMap],
      typeof: [HookMap],
      importCall: [Hook],
      topLevelAwait: [Hook],
      call: [HookMap],
      callMemberChain: [HookMap],
      memberChainOfCallMemberChain: [HookMap],
      callMemberChainOfCallMemberChain: [HookMap],
      optionalChaining: [Hook],
      new: [HookMap],
      expression: [HookMap],
      expressionMemberChain: [HookMap],
      unhandledExpressionMemberChain: [HookMap],
      expressionConditionalOperator: [Hook],
      expressionLogicalOperator: [Hook],
      program: [Hook],
      finish: [Hook]
    },
    sourceType: 'auto',
    scope: undefined,
    state: undefined,
    comments: undefined,
    semicolons: undefined,
    statementPath: undefined,
    prevStatement: undefined,
    currentTagData: undefined
  },
  parserOptions: undefined,
  generator: JavascriptGenerator {},
  generatorOptions: undefined,
  resolveOptions: undefined
}

My issue https://github.com/callstack/linaria/issues/897 is the same problem, manifested differently due to me overriding the entry module.

While making the injection check in react-refresh-webpack-plugin like so match(moduleData.matchResource || moduleData.resource) && it solves some of the cases, but the above module is still getting through and should be excluded at this step.

It would be helpful if someone understood the nature of .webpack[javascript/auto] type files. I couldn't find anything on the internet so I'm a bit stumped for now.

ntucker avatar Feb 07 '22 05:02 ntucker

It sounds like preventing react fast refresh from being injected into the CSS virtual modules (or whatever they are called) is the key to solving some of the issues here.

I submitted a PR to react fast refresh plugin: https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/726

With that PR we can now exclude CSS virtual modules generated by linaria.

nicholasio avatar Feb 10 '23 17:02 nicholasio

This issue might have been fixed by https://github.com/pmmmwh/react-refresh-webpack-plugin/pull/769

malash avatar Aug 26 '23 16:08 malash