linaria
linaria copied to clipboard
webpack build silently fails after Linaria update
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)
Hi @kryops!
Probably, you have a circular dependency somewhere. However, it is not a legit reason to crash without any error messages :)
@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.
Anyway, lets keep this issue open. I'll think how to improve DX here.
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 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.
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 what do you use as a transpiler? Babel, esbuild, swc, tsc, something else?
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 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.
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?
@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.
@PierreGUI Thank you! I'll check your example.
+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?
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).
Is there any progress on this issue at the moment?
@phyzess The new version of Linaria (v5) should fix the problem. It worked for me at least.
Unfortunately didn't work for me (Linaria 5.0.2)