linaria icon indicating copy to clipboard operation
linaria copied to clipboard

webpack build silently fails after Linaria update

Open kryops opened this issue 2 years ago • 17 comments

Hi there,

I have a mysterious problem in one of my projects after updating to the current version of Linaria: The webpack build seems to crash, but it does not report any error - it just exits without writing anythin on disk.

I managed to track down the change in Linaria that causes the problem, I just can't figure out what's happening exactly. Thanks for having a look! 😅

Environment

  • Linaria version: 4.2.2
  • Bundler (+ version): webpack 5.75.0
  • Node.js version: 19.1.0
  • OS: ArchLinux

Description

I do not really understand what is happening - maybe an error that leads to a crash, but the error is then swallowed somehow?

I managed to track it down to https://github.com/callstack/linaria/pull/1086 (CC @Anber ): It starts working again when I pin @linaria/babel-preset to 4.2.2, or comment out the await mutex that was introduced there.

Reproducible Demo

I was unable to provide a minimal reproduction, as only one of my projects is affected, and I don't know which code there causes it.

I created a branch with a reproduction here: https://github.com/kryops/vlight/tree/linaria-babel-preset-error

Just execute yarn, which should build everything.

The output is:

...
[BABEL] Note: The code generator has deoptimised the styling of /home/michael/git/vlight/node_modules/@mdi/js/mdi.js as it exceeds the max of 500KB.
[BABEL] Note: The code generator has deoptimised the styling of /home/michael/git/vlight/node_modules/@mdi/js/mdi.js as it exceeds the max of 500KB.
➤ YN0000: Done with warnings in 42s 859ms

(the [BABEL] message is repeated 4 times)

Nothing is written into the frontend/dist folder.

The successful build output on the main branch looks like this:

...
[BABEL] Note: The code generator has deoptimised the styling of /home/michael/git/vlight/node_modules/@mdi/js/mdi.js as it exceeds the max of 500KB.
[BABEL] Note: The code generator has deoptimised the styling of /home/michael/git/vlight/node_modules/@mdi/js/mdi.js as it exceeds the max of 500KB.
6 assets
774 modules
webpack 5.75.0 compiled successfully in 33886 ms
➤ YN0000: Done with warnings in 54s 906ms

(the [BABEL] message is repeated more than 4 times)

kryops avatar Nov 26 '22 08:11 kryops

Hi @kryops!

Probably, you have a circular dependency somewhere. However, it is not a legit reason to crash without any error messages :)

Anber avatar Nov 26 '22 17:11 Anber

@Anber that's it, thanks so much! I hadn't noticed the circular imports - after removing them, it starts building again 😳

For anyone having the same issue: I used https://github.com/acrazing/dpdm to find the circular dependencies in my code.

kryops avatar Nov 26 '22 18:11 kryops

Anyway, lets keep this issue open. I'll think how to improve DX here.

Anber avatar Nov 26 '22 18:11 Anber

My team run into the same with circular dependencies. Are there already thoughts on how to solve this?

Based on a short investigation, I'd expect returning a warning or error in this case might not be too hard.

But is this actually fixable to make circular dependencies work (as you would expect when using es-module syntax)?

If my time allows I would even consider to have a look, a hint where to start would be nice 🙂

garthenweb avatar Nov 27 '22 17:11 garthenweb

@garthenweb since we have to statically evaluate a lot of things (from a dependency graph to actual values of interpolated identifiers), it can be tricky to support circular dependencies, mainly because most libraries are still cjm, and we have to support, parse and evaluate them as well.

I guess you don't use circular dependencies in your interpolated values. Linaria tries to evaluate some code which probably isn't required for styles but, for some reason, wasn't shaken out by shaker. So the main problem here is not in circular dependencies but in too relaxed @linaria/shaker that doesn't remove redundant code.

Could you please try to make a repo that reproduces that error? If we can find a reason why shaker doesn't remove the redundant code, we not only fix your problem with circular dependencies but also improve speed for the rest of the users.

Anber avatar Nov 27 '22 21:11 Anber

Thanks for the hints, that makes sense. When exploring the behaviour I found similarities to what you describe. If we can remove the unneeded parsing, the issue would reduce quite a lot. It might be sufficient for 95% of the cases. In combination with a proper warning in case it still happens it is most probably easy enough to work around.

I will try to come up with an example repo as soon as I find time for it :)

garthenweb avatar Nov 28 '22 14:11 garthenweb

@garthenweb what do you use as a transpiler? Babel, esbuild, swc, tsc, something else?

Anber avatar Nov 29 '22 14:11 Anber

Short answer: Webpack + linaria plugin with custom babel options:

{
  plugins: [
    '@babel/plugin-syntax-jsx',
    '@babel/plugin-proposal-class-properties',
    [
      // required for legacy desktop to parse the syntax
      '@babel/plugin-proposal-decorators',
      {
        decoratorsBeforeExport: true,
      },
    ],
  ],
  presets: ['@babel/preset-typescript', '@linaria'],
}

Long version: It's a bit complicated:

  • we use webpack (with razzel), but replace the babel and typescript transform with esbuild (as a webpack plugin) executed in a thread loader thread-loader
  • we add linaria in front of esbuild to transpile as the first transform (without the thread loader)

As we first run run linaria and esbuild later, I expect the complex setup does not play a role. But currently I cannot verify.

garthenweb avatar Nov 29 '22 15:11 garthenweb

@garthenweb maybe it does. If you have a lot of packages that are transpiled with esbuild, Linaria may struggle with resolving the whole dependency tree. I'm going to add esbuild to the list of tested compilers and check if it works or not. I'll let you know in a day.

Anber avatar Nov 29 '22 19:11 Anber

Trying to update from Linaria 2.3.1 I also experience this issue where webpack stops without error. When provided with the option progress, webpack gets stuck: 10% building 0/x entries 1/y dependencies 0/z modules

Looking at this issue, I suspect we have circular dependencies in our app too. So I ran dpdm --no-warning --no-tree ./src/*.ts and found only type dependencies in the report (the output with -T option is green ✅ ).
Since then, I've been looking for a reproduction case.

Setup

  • Webpack 5.75
  • Babel 7.13 with typescript preset
  • React 18
  • Linaria 4.3

Mini repro case

The smallest code to confuse Linaria's build is the following:

App.ts

import { styled } from '@linaria/react'
import * as React from 'react'
import B from './B'

export const App = styled.div``

B.ts

import App from './App'
dpdm --no-warning --no-tree ./src/app.ts
✔ [3/3] Analyze done!
• Circular Dependencies
  1) src/A.ts -> src/B.ts
  
 dpdm -T --no-warning --no-tree ./src/app.ts
✔ [1/1] Analyze done!
• Circular Dependencies
  ✅ Congratulations, no circular dependency was found in your project.

PS: I'm also looking at more intricate examples because I feel this doesn't give the full picture. I've been able to build similar code in some cases, but at some point it fails when the dependency tree grows. I have a hunch enum are part of the problem (because are type and value at the same time) maybe?

PierreGUI avatar Nov 30 '22 10:11 PierreGUI

@garthenweb I've checked how Linaria works with esbuild. Half of the test cases don't work. It means that if imported code is transpiled with esbuild, Linaria cannot resolve its dependency graph and detect unnecessary code. I'll fix it asap.

Anber avatar Nov 30 '22 16:11 Anber

@PierreGUI Thank you! I'll check your example.

Anber avatar Nov 30 '22 16:11 Anber

+1

I have encountered this issue too. I am using npm package inversify which has a circular require inside it. After some investgations into internal codes of linaria, I make it work by copying the default rules of EvalRule

https://github.com/callstack/linaria/blob/master/docs/CONFIGURATION.md#:~:text=The%20default%20setup%20is%3A

Actually the default rules in the document is not the default rules in the code. That's confusing.

The await mutex takes me a lot of debugging time to find it because everything become idle. Is there any way to make a "timeout" to inform possible circular deps?

hjkcai avatar Jan 11 '23 09:01 hjkcai

I've tried again with latest packages:

"@linaria/react": "^4.3.6",
"@linaria/core": "^4.2.8",
"@linaria/webpack-loader": "^4.1.15",
"webpack": "^5.76.1",

The above reproduction case doesn't fail silently anymore, and neither does my entire build.
This being said, I experience extremely slow build (10 minutes instead of 30 seconds). Use of cache does not seem to improve subsequent builds time.
Unfortunately, it's hard to imagine working with this long build time. I've tried to rule out some files in the webpack config, without success. Something seems off for sure, I'm looking at https://github.com/callstack/linaria/issues/1199#issuecomment-1466373658 for example, as it appears to be similar to my issue (files parsed multiple times).

PierreGUI avatar Mar 14 '23 15:03 PierreGUI

Is there any progress on this issue at the moment?

phyzess avatar Oct 11 '23 02:10 phyzess

@phyzess The new version of Linaria (v5) should fix the problem. It worked for me at least.

PierreGUI avatar Oct 24 '23 12:10 PierreGUI

Unfortunately didn't work for me (Linaria 5.0.2)

namoko avatar Nov 06 '23 14:11 namoko