I need to configure next.config.js file in order to use in the same time two different loaders.
This is the first:
const withSass = require('#zeit/next-sass');
module.exports = withSass({
cssModules: true,
cssLoaderOptions: {
importLoaders: 1,
localIdentName: "[local]___[hash:base64:5]",
}
})
And this is the second:
const withSass = require('#zeit/next-sass');
const withCSS = require('#zeit/next-css');
module.exports = withCSS(withSass({
webpack (config, options) {
config.module.rules.push({
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000
}
}
})
return config
}
}))
Individually they work great!
But I'm not able to combine them in a single rule so that both can work together.
Thanks for your help!!
You should use next-compose-plugins. Here is a link below for additional reference.
How can I combine multiple loaders (CSS, LESS, ttf, etc) in NextJS config file?
But the code below should solve your issue:
Install
yarn add --dev #zeit/next-css
yarn add --dev #zeit/next-sass file-loader url-loader
Update your next.config.js file
const withPlugins = require('next-compose-plugins');
const sass = require("#zeit/next-sass")
const css = require("#zeit/next-css")
const nextConfig = {
webpack: function (config) {
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
name: '[name].[ext]'
}
}
})
return config
}
}
module.exports = withPlugins([
[css],
[sass, {
cssModules: true
}]
], nextConfig);
Note: You should now be able to import scss modules like this:
import styles from 'your-file-name.module.scss'
Note: Watch out for vendors libs that are not formatted properly in that case you should import as follows:
import "slick-carousel/slick/slick-theme.css";
import "slick-carousel/slick/slick.css";
Related
How can I migrate and change the next.config.js file from #zeit/next-sass to use Next.js built-in support for Sass?
https://www.npmjs.com/package/#zeit/next-sass
const withSass = require('#zeit/next-sass')
const withCSS = require("#zeit/next-css");
module.exports = withCSS(withSass({
webpack(config, options) {
config.module.rules.push({
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000
}
}
});
return config;
}
}));
Next.js built-in Sass support requires you to install sass as a dependency.
$ npm install sass
You can then simply remove #zeit/next-sass and #zeit/next-css plugins from your config.
// next.config.js
module.exports = {
webpack(config, options) {
config.module.rules.push({
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000
}
}
});
return config;
}
};
For further details check the official Sass support docs.
Is it possible to get the CSS for a Vue component, and attach it as a string to a component when building a library for use at runtime?
vue-cli-service build --mode production --target lib --name components src/index.ts
I currently achieve this for some custom js using a custom block:
vue.config.js:
...
rules: [
{
resourceQuery: /blockType=client-script/,
use: './client-script-block',
},
],
},
...
client-script-block.js:
module.exports = async function () {
return `export default function (Component) {
Component.options.__client_script = ${JSON.stringify(this.resourcePath)};
}`;
};
which then exposed the string in the Vue app that uses the library. But achieving the same thing with CSS doesn't seem to play ball.
You could take a look at this CSS Extraction modules from VueLoader, that extracts the CSS from specific file or files, and stores it in a custom file, that you could then load dynamically in runtime, like:
Install:
npm install -D mini-css-extract-plugin
// webpack.config.js
var MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
// other options...
module: {
rules: [
// ... other rules omitted
{
test: /\.css$/,
use: [
process.env.NODE_ENV !== 'production'
? 'vue-style-loader'
: MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins: [
// ... Vue Loader plugin omitted
new MiniCssExtractPlugin({
filename: 'style.css'
})
]
}
Reference: https://vue-loader.vuejs.org/guide/extract-css.html#webpack-4:
Another approach:
// webpack.config.js
var ExtractTextPlugin = require("extract-text-webpack-plugin")
module.exports = {
// other options...
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
extractCSS: true
}
}
]
},
plugins: [
new ExtractTextPlugin("style.css")
]
}
Reference: https://vue-loader-v14.vuejs.org/en/configurations/extract-css.html
Also here you have a complete guide for extracting the CSS from a SSR (Server Side Rendered) apps: https://ssr.vuejs.org/guide/css.html#enabling-css-extraction
I'm am using TS + CSS + SCSS in nextJS. I will import some CSS files, but I want to set cssModule:false to those CSS files, then I will import my own SCSS files and set cssModule:true.
The below is my code in next.config.js, it transfers CSS files to module.
const withSass = require("#zeit/next-sass");
const withTypescript = require("#zeit/next-typescript");
const withCSS = require("#zeit/next-css");
module.exports = withTypescript(
withCSS(
withSass({
cssModules: true
})
)
);
Could you please advise me on the right approach of importing CSS files?
The configuration of next-css is global, you either using cssModules or not.
My solution for this was to configure webpack manually to not apply cssModules on files with .global.css suffix.
config.module.rules.forEach(rule => {
if (rule.test.toString().includes('.scss')) {
rule.rules = rule.use.map(useRule => {
if (typeof useRule === 'string') {
return {
loader: useRule,
};
}
if (useRule.loader.startsWith('css-loader')) {
return {
oneOf: [
{
test: /\.global\.scss$/,
loader: useRule.loader,
options: {
...useRule.options,
modules: false,
},
},
{
loader: useRule.loader,
options: useRule.options,
},
],
};
}
return useRule;
});
delete rule.use;
}
});
There is an open PR for next-css to include similar solution to the lib.
I'm completely new to NextJS, trying out its SSR features.
I want to setup loaders where I can load 4 types of files into the app:
*.module.css;
*.module.scss;
*.css;
*.scss;
1 and 2 are loaded with CSS modules and 3 and 4 just as regular CSS/SCSS.
How can I do this with #zeit/next-css and #zeit/next-sass?
Currently next-css / next-sass are not supporting this feature, but you can add it by your self to the webpack config.
I've similar but the opposite option, I'm enabling module: true for all imports and for all files that I want to be treated as regular css in (ie. global), I need to add, .global suffix.
This is my modification to the webpack config:
// next.config.js
config.module.rules.forEach(rule => {
if (rule.test && rule.test.toString().includes('.scss')) {
rule.rules = rule.use.map(useRule => {
if (typeof useRule === 'string') {
return {
loader: useRule,
};
}
if (useRule.loader.startsWith('css-loader')) {
return {
oneOf: [
{
test: /\.global\.scss$/,
loader: useRule.loader,
options: {
...useRule.options,
modules: false,
},
},
{
loader: useRule.loader,
options: useRule.options,
},
],
};
}
return useRule;
});
delete rule.use;
}
});
This piece of code looks for the css-loader config and modifies it to support .global.scss suffix.
BTW, you can get updated by following this PR
EDIT
Next version ^9.2.0 has now a native support for css imports with some restrictions.
just wondering whether you've managed to get this working?
I managed to come close with something similar to Felix's answer to get .module.scss and .scss files working with .css only working in #imports within a .scss/.module.scss file. Really would like to be able to get .css files working whilst imported from a component.
My next.config.js file for reference below
const withSass = require('#zeit/next-sass');
const withPlugins = require('next-compose-plugins');
const withSourceMaps = require('#zeit/next-source-maps');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const sassConfig = {
cssModules: true,
cssLoaderOptions: {
importLoaders: 2,
localIdentName: '[local]___[hash:base64:5]',
},
webpack: config => {
config.module.rules.forEach(rule => {
if (rule.test && rule.test.toString().match(/\.(sa|sc)ss$/)) {
rule.rules = rule.use.map(useRule => {
if (typeof useRule === 'string') {
return { loader: useRule };
}
if (useRule.loader.startsWith('css-loader')) {
return {
oneOf: [
{
test: new RegExp(/\module.(sa|sc)ss$/),
exclude: new RegExp(/\.css$/),
loader: useRule.loader,
options: useRule.options,
},
{
loader: useRule.loader,
options: {},
},
],
};
}
return useRule;
});
delete rule.use;
}
});
return config;
},
};
module.exports = withPlugins(
[[withSourceMaps], [withSass, sassConfig]]
);
I am trying to integrate Nextjs with graphql-tag/loader, This is my next.config.js file:
const withSass = require('#zeit/next-sass')
const graphqlLoader = require('graphql-tag/loader')
module.exports = withSass({
webpack: (config, { buildId, dev, isServer, defaultLoaders }) => {
config.module.rules.push({
test: /\.(graphql|gql)$/,
loader: graphqlLoader,
exclude: /node_modules/
})
return config
}
})
I am unable to build, I get the error below:
/HOME/node_modules/graphql-tag/loader.js:43
this.cacheable();
^
TypeError: Cannot read property 'cacheable' of undefined
Please help.
i made it working in my setup as follows. Not sure what is wrong in your code, but you can try it and see if it is working :) You can use next js plugin for it. Maybe the order of plugins matter. Here is my config. There are some additional code, but i am sure, that you will get it what you need from it. As for the libraries version "next": "6.1.1", "next-optimized-images": "1.4.1", "next-plugin-graphql": "^0.0.1",
const withSass = require("#zeit/next-sass");
const webpack = require("webpack");
const withGraphQL = require("next-plugin-graphql");
const withOptimizedImages = require("next-optimized-images");
module.exports = withOptimizedImages(
withGraphQL(
withSass({
cssModules: true,
cssLoaderOptions: {
importLoaders: 1,
localIdentName: "[local]___[hash:base64:5]"
},
webpack: config => {
config.plugins.push(
new webpack.ContextReplacementPlugin(
/graphql-language-service-interface[\\/]dist$/,
new RegExp(`^\\./.*\\.js$`)
)
);
return config;
}
})
)
);
If you would prefer just to modify your code and do not install plugins you can inspire yourself from this next-graphql-plugin. The plugin is working for me, the difference from your setup is that they have rule configured as follows
config.module.rules.push({
test: /\.(graphql|gql)$/,
include: [dir],
exclude: /node_modules/,
use: [
{
loader: 'graphql-tag/loader'
}
]
})