fix(nextjs): add Next.js config enhancer for supporting css moduels in workspace libs (#4047)

This commit is contained in:
Jack Hsu 2020-11-09 11:52:03 -05:00 committed by GitHub
parent 1f66f4cc42
commit a297db6324
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 117 additions and 7 deletions

View File

@ -7,7 +7,6 @@ import {
readJson,
runCLI,
runCLIAsync,
supportUi,
uniq,
updateFile,
} from '@nrwl/e2e/utils';
@ -87,6 +86,24 @@ forEachCli('nx', () => {
const mainPath = `apps/${appName}/pages/index.tsx`;
updateFile(mainPath, `import '@proj/${libName}';\n` + readFile(mainPath));
// Update lib to use css modules
updateFile(
`libs/${libName}/src/lib/${libName}.tsx`,
`
import React from 'react';
import styles from './style.module.css';
export function Test() {
return <div className={styles.container}>Hello</div>;
}
`
);
updateFile(
`libs/${libName}/src/lib/style.module.css`,
`
.container {}
`
);
await checkApp(appName, {
checkUnitTest: true,
checkLint: true,

View File

@ -0,0 +1,91 @@
const { join } = require('path');
const { appRootPath } = require('@nrwl/workspace/src/utils/app-root');
const { workspaceLayout } = require('@nrwl/workspace/src/core/file-utils');
function regexEqual(x, y) {
return (
x instanceof RegExp &&
y instanceof RegExp &&
x.source === y.source &&
x.global === y.global &&
x.ignoreCase === y.ignoreCase &&
x.multiline === y.multiline
);
}
function withNx(nextConfig = {} as any) {
const userWebpack = nextConfig.webpack || ((x) => x);
return {
...nextConfig,
/*
* Modify the Next.js webpack config to allow workspace libs to use css modules.
*
* Note: This would be easier if Next.js exposes css-loader and sass-loader on `defaultLoaders`.
*/
webpack: (config, { defaultLoaders }) => {
// Include workspace libs in css/sass loaders
const includes = [join(appRootPath, workspaceLayout().libsDir)];
const nextCssLoaders = config.module.rules.find(
(rule) => typeof rule.oneOf === 'object'
);
// webpack config is not as expected
if (!nextCssLoaders) return config;
/*
* 1. Modify css loader to enable module support for workspace libs
*/
const nextCssLoader = nextCssLoaders.oneOf.find(
(rule) =>
rule.sideEffects === false && regexEqual(rule.test, /\.module\.css$/)
);
// Might not be found if Next.js webpack config changes in the future
if (nextCssLoader) {
nextCssLoader.issuer.or = nextCssLoader.issuer.and
? nextCssLoader.issuer.and.concat(includes)
: includes;
delete nextCssLoader.issuer.and;
}
/*
* 2. Modify sass loader to enable module support for workspace libs
*/
const nextSassLoader = nextCssLoaders.oneOf.find(
(rule) =>
rule.sideEffects === false &&
regexEqual(rule.test, /\.module\.(scss|sass)$/)
);
// Might not be found if Next.js webpack config changes in the future
if (nextSassLoader) {
nextSassLoader.issuer.or = nextSassLoader.issuer.and
? nextSassLoader.issuer.and.concat(includes)
: includes;
delete nextSassLoader.issuer.and;
}
/*
* 3. Modify error loader to ignore css modules used by workspace libs
*/
const nextErrorCssModuleLoader = nextCssLoaders.oneOf.find(
(rule) =>
rule.use &&
rule.use.loader === 'error-loader' &&
rule.use.options &&
(rule.use.options.reason ===
'CSS Modules \u001b[1mcannot\u001b[22m be imported from within \u001b[1mnode_modules\u001b[22m.\n' +
'Read more: https://err.sh/next.js/css-modules-npm' ||
rule.use.options.reason ===
'CSS Modules cannot be imported from within node_modules.\nRead more: https://err.sh/next.js/css-modules-npm')
);
// Might not be found if Next.js webpack config changes in the future
if (nextErrorCssModuleLoader) {
nextErrorCssModuleLoader.exclude = includes;
}
return userWebpack(config);
},
};
}
module.exports = withNx;

View File

@ -1,25 +1,27 @@
const withNx = require('@nrwl/next/plugins/with-nx');
<% if (style === 'less') { %>
const withLess = require('@zeit/next-less');
module.exports = withLess({
module.exports = withLess(withNx({
// Set this to true if you use CSS modules.
// See: https://github.com/css-modules/css-modules
cssModules: false
});
}));
<% } else if (style === 'styl') { %>
const withStylus = require('@zeit/next-stylus');
module.exports = withStylus({
module.exports = withStylus(withNx({
// Set this to true if you use CSS modules.
// See: https://github.com/css-modules/css-modules
cssModules: false
});
}));
<% } else if (
style === 'styled-components'
||style === '@emotion/styled'
|| style === 'styled-jsx'
|| style === 'none'
) { %>
module.exports ={};
module.exports = withNx({});
<% } else {
// Defaults to CSS/SASS (which don't need plugin as of Next 9.3) %>
module.exports ={};
module.exports = withNx({});
<% } %>