-
Notifications
You must be signed in to change notification settings - Fork 414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Linaria + Next.js webpack configuration #318
Comments
Have you added |
@satya164 Didn't think to since it's hidden with next.js. Extending webpack.. Following the
this is the compile error I get:
|
I'm not placing
|
@satya164 Adding it correctly did the trick. Feels a little hacky but that's next.js for you I guess. Here's the confg setup: next.config.js
|
Following your way, I find it working only in dev but not in the production build. |
hey @orpheus thanks for your answer, I could simplify this even: add linaria yarn add -E linaria
{
"presets": ["next/babel", "linaria/babel"]
}
const withCSS = require("@zeit/next-css");
module.exports = withCSS({
webpack(config, { isServer }) {
config.module.rules[0].use = [
config.module.rules[0].use,
{
loader: "linaria/loader",
options: {
sourceMap: process.env.NODE_ENV !== "production"
}
}
];
return config;
}
}); I made a tutorial: https://gist.github.com/LukasBombach/dc46546919ecf71b2aa68688ee767e4e |
Thank @LukasBombach. Your config is really nice and clean. However, it doesn't work with latest Next.js 9.4 for use: [
'.../node_modules/@next/react-refresh-utils/loader.js',
{ loader: 'next-babel-loader', options: [Object] }
] So I have adjusted the config a little to cater for both dev and production build: const withCSS = require('@zeit/next-css');
module.exports = withCSS({
webpack(config) {
// retrieve the rule without knowing its order
const jsLoaderRule = config.module.rules.find(
(rule) => rule.test instanceof RegExp && rule.test.test('.js')
);
const linariaLoader = {
loader: 'linaria/loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production',
},
};
if (Array.isArray(jsLoaderRule.use)) {
jsLoaderRule.use.push(linariaLoader);
} else {
jsLoaderRule.use = [jsLoaderRule.use, linariaLoader];
}
return config;
},
}); |
UPDATE No need to read the below. Seems that I was doing too much. A good example does exist, but finding it is difficult. Fortunately it seems to be on the radar. Since there isn't a solid example of Next.js with Linaria from my Googling, I've pieced together a config based on this issue and the Linaria Webpack documentation. I'm getting the following error logged in my terminal and in the browser the HTML
It compiles successfully, but below is the error:
I found this issue from Would appreciate any help or hints! This is the code I've pieced together
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const withCSS = require('@zeit/next-css');
module.exports = withCSS({
webpack(config) {
// https://github.com/callstack/linaria/issues/318
// retrieve the rule without knowing its order
const jsLoaderRule = config.module.rules.find(
(rule) => rule.test instanceof RegExp && rule.test.test('.js')
);
const linariaLoader = {
loader: 'linaria/loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production',
},
};
if (Array.isArray(jsLoaderRule.use)) {
jsLoaderRule.use.push(linariaLoader);
} else {
jsLoaderRule.use = [jsLoaderRule.use, linariaLoader];
}
// https://github.com/callstack/linaria/blob/master/docs/BUNDLERS_INTEGRATION.md#webpack
config.module.rules.push({
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV !== 'production',
},
},
{
loader: 'css-loader',
options: {
sourceMap: process.env.NODE_ENV !== 'production',
},
},
],
});
config.plugins.push(
new MiniCssExtractPlugin({
filename: process.env.NODE_ENV !== 'production'
? 'styles.css'
: 'styles-[contenthash].css',
}),
);
return config;
},
});
import { styled } from 'linaria/react';
import Head from 'next/head';
const Header = styled.h1`
font-family: sans-serif;
font-size: 48px;
color: #f15f79;
`;
export default () => (
<>
<Head>
<title>Create Next App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<Header>Hello world!</Header>
</>
); |
For me, this library works well |
Is this still relevant with Nest js 12 .I am getting the following error while using this configuration in next.config.js
|
I created a new repo recently based on this comment here #589 (comment) by @anulman This is for Next.js 12 with Linaria 4 + it has Inline CSS Extraction https://github.com/LukasBombach/nextjs-linaria You can check out the next config here https://github.com/LukasBombach/nextjs-linaria/blob/main/next.config.js const _ = require("lodash");
const BABEL_LOADER_STRING = "babel/loader";
const makeLinariaLoaderConfig = babelOptions => ({
loader: require.resolve("@linaria/webpack-loader"),
options: {
sourceMap: true,
extension: ".linaria.module.css",
babelOptions: _.omit(
babelOptions,
"isServer",
"distDir",
"pagesDir",
"development",
"hasReactRefresh",
"hasJsxRuntime"
),
},
});
let injectedBabelLoader = false;
function crossRules(rules) {
for (const rule of rules) {
if (typeof rule.loader === "string" && rule.loader.includes("css-loader")) {
if (rule.options && rule.options.modules && typeof rule.options.modules.getLocalIdent === "function") {
const nextGetLocalIdent = rule.options.modules.getLocalIdent;
rule.options.modules.mode = "local";
rule.options.modules.auto = true;
rule.options.modules.exportGlobals = true;
rule.options.modules.exportOnlyLocals = true;
rule.options.modules.getLocalIdent = (context, _, exportName, options) => {
if (context.resourcePath.includes(".linaria.module.css")) {
return exportName;
}
return nextGetLocalIdent(context, _, exportName, options);
};
}
}
if (typeof rule.use === "object") {
if (Array.isArray(rule.use)) {
const babelLoaderIndex = rule.use.findIndex(
({ loader }) => typeof loader === "string" && loader.includes(BABEL_LOADER_STRING)
);
const babelLoaderItem = rule.use[babelLoaderIndex];
if (babelLoaderIndex !== -1) {
rule.use = [
...rule.use.slice(0, babelLoaderIndex),
babelLoaderItem,
makeLinariaLoaderConfig(babelLoaderItem.options),
...rule.use.slice(babelLoaderIndex + 2),
];
injectedBabelLoader = true;
}
} else if (typeof rule.use.loader === "string" && rule.use.loader.includes(BABEL_LOADER_STRING)) {
rule.use = [rule.use, makeLinariaLoaderConfig(rule.use.options)];
injectedBabelLoader = true;
}
crossRules(Array.isArray(rule.use) ? rule.use : [rule.use]);
}
if (Array.isArray(rule.oneOf)) {
crossRules(rule.oneOf);
}
}
}
function withLinaria(nextConfig = {}) {
return {
...nextConfig,
webpack(config, options) {
crossRules(config.module.rules);
if (!injectedBabelLoader) {
config.module.rules.push({
test: /\.(tsx?|jsx?)$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
options: linariaWebpackLoaderConfig.options.babelOptions,
},
linariaWebpackLoaderConfig,
],
});
}
if (typeof nextConfig.webpack === "function") {
return nextConfig.webpack(config, options);
}
return config;
},
};
}
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
};
module.exports = withLinaria(nextConfig); |
It is not working with the lastest nextjs version |
@LukasBombach Thank you so much for the details .This works like charm but i have run into an issue where i am getting the below error when i try to build the project
|
@adamhenson @LukasBombach do your approaches work like styled-components? That is, do they embed the initial (first-render) CSS into the HTML? If not, these approaches will suffer from massive layout shift as the CSS loads after the HTML. (This is the problem that I saw the next-linaria package----it does not embed the linaria CSS into the HTML, so you'll see the page jump.) And if the answer is no, then this issue needs to be opened---the whole point of next.js is to minimize things like layout shift 😉 |
@frankandrobot My comment was over 2.5 years ago, based on an older version of Next.js, but yes it was working fine eventually. Layout shift for me is unacceptable, hence the point of why I was using Linaria back then (a zero run-time solution). It was working fine for me, but not very well with MUI. I have since stopped using Linaria in favor of Tailwind. |
LOL. You could have just said I don’t use linaria anymore :-)
It’s unfortunate since linaria/vanilla-extract give you the same benefits as JSX (typescript/data structures) but w/o the runtime overhead of styled components
On Dec 11, 2022, at 2:14 PM, Adam ***@***.******@***.***>> wrote:
@frankandrobot<https://github.com/frankandrobot> I don't see any value to your comment. My comment was over 2.5 years ago, based on an older version of Next.js. Layout shift for me is completely unacceptable hence the point of using Linaria (a zero run-time solution). And in that regard, I don't need to be told the point of Next.js. I have since stopped using Linaria and leaned more into solutions like Tailwind.
—
Reply to this email directly, view it on GitHub<#318 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AAGAGMP3ZQVVE6YRGLWRLH3WMYYZRANCNFSM4GZIUHHA>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
Linaria or styled components do not inherently implement inlining critical css. But you can make any next app do that by overwriting the way next/head emits its css. In the repo I made I am actually doing that, inlining the css next js would emit as files |
@LukasBombach sweet. Thanks so much. 👍 That repo should probably made as the official example 😄 |
I'd really love to see any official interface instead of having to use low-level code-snippets to make it work. |
Using react and nextjs. The div element gets the className:
ci74fup
but no styles are applied. What am I missing?Am I limited to using only the react-helpers?
.babelrc
{ "presets": ["next/babel", "linaria/babel"] }
The text was updated successfully, but these errors were encountered: