Created
May 4, 2020 16:33
-
-
Save denistex/689cc39ca68cf329eb9c32c155187ef6 to your computer and use it in GitHub Desktop.
Rescript to connect antd-scss-theme-plugin correctly
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict' | |
const { getPaths, edit } = require('@rescripts/utilities') | |
const loaderUtils = require('loader-utils') | |
const path = require('path') | |
const paths = require('react-scripts/config/paths') | |
const MiniCssExtractPlugin = require('mini-css-extract-plugin') | |
const AntdScssThemePlugin = require('@atbtech/antd-scss-theme-plugin') | |
const postcssNormalize = require('postcss-normalize') | |
const isEnvDevelopment = process.env.NODE_ENV === 'development' | |
const isEnvProduction = process.env.NODE_ENV === 'production' | |
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false' | |
const regexes = { | |
css: /\.css$/, | |
cssModule: /\.module\.css$/, | |
less: /\.less$/, | |
lessModule: /\.module\.less$/, | |
sass: /\.(scss|sass)$/, | |
sassModule: /\.module\.(scss|sass)$/ | |
} | |
const newStyleLoaders = [ | |
{ | |
test: regexes.css, | |
exclude: regexes.cssModule, | |
use: getStyleLoaders({ | |
importLoaders: 1, | |
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment | |
}), | |
// Don't consider CSS imports dead code even if the | |
// containing package claims to have no side effects. | |
// Remove this when webpack adds a warning or an error for this. | |
// See https://github.com/webpack/webpack/issues/6571 | |
sideEffects: true | |
}, | |
// Adds support for CSS Modules (https://github.com/css-modules/css-modules) | |
// using the extension .module.css | |
{ | |
test: regexes.cssModule, | |
use: getStyleLoaders({ | |
importLoaders: 1, | |
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, | |
modules: { | |
getLocalIdent: getCSSModuleLocalIdent | |
} | |
}) | |
}, | |
// Opt-in support for LeSS (using .less extension). | |
// By default we support LESS Modules with the | |
// extension .module.less | |
{ | |
test: regexes.less, | |
exclude: regexes.lessModule, | |
use: getStyleLoaders( | |
{ | |
importLoaders: 3, | |
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment | |
}, | |
'less-loader', | |
{ | |
lessOptions: { | |
javascriptEnabled: true, | |
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment | |
} | |
} | |
), | |
// Don't consider CSS imports dead code even if the | |
// containing package claims to have no side effects. | |
// Remove this when webpack adds a warning or an error for this. | |
// See https://github.com/webpack/webpack/issues/6571 | |
sideEffects: true | |
}, | |
// Adds support for CSS Modules, but using LESS | |
// using the extension .module.less | |
{ | |
test: regexes.lessModule, | |
use: getStyleLoaders( | |
{ | |
importLoaders: 3, | |
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, | |
modules: { | |
getLocalIdent: getCSSModuleLocalIdent | |
} | |
}, | |
'less-loader', | |
{ | |
lessOptions: { | |
javascriptEnabled: true, | |
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment | |
} | |
} | |
) | |
}, | |
// Opt-in support for SASS (using .scss or .sass extensions). | |
// By default we support SASS Modules with the | |
// extensions .module.scss or .module.sass | |
{ | |
test: regexes.sass, | |
exclude: regexes.sassModule, | |
use: getStyleLoaders( | |
{ | |
importLoaders: 3, | |
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment | |
}, | |
'sass-loader' | |
), | |
// Don't consider CSS imports dead code even if the | |
// containing package claims to have no side effects. | |
// Remove this when webpack adds a warning or an error for this. | |
// See https://github.com/webpack/webpack/issues/6571 | |
sideEffects: true | |
}, | |
// Adds support for CSS Modules, but using SASS | |
// using the extension .module.scss or .module.sass | |
{ | |
test: regexes.sassModule, | |
use: getStyleLoaders( | |
{ | |
importLoaders: 3, | |
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment, | |
modules: { | |
getLocalIdent: getCSSModuleLocalIdent | |
} | |
}, | |
'sass-loader' | |
) | |
} | |
] | |
const isStyleLoaders = x => x && Array.isArray(x.oneOf) | |
function withLessLoader (config) { | |
return edit( | |
section => { | |
const res = Object.values(regexes).map(x => x.toString()) | |
const filtered = | |
section.oneOf.filter(x => !x.test || !res.includes(x.test.toString())) | |
const jsLoaders = filtered.slice(0, filtered.length - 1) | |
const fileLoader = filtered[filtered.length - 1] | |
section.oneOf = [].concat(jsLoaders, newStyleLoaders, fileLoader) | |
return section | |
}, | |
getPaths(isStyleLoaders, config), | |
config | |
) | |
} | |
// https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/config/webpack.config.js | |
// Modifications: | |
// 1. Wrap the preProcessor with AntdScssThemePlugin. | |
// 2. Remove resolving of preProcessor (it should be overriden by | |
// AntdScssThemePlugin.themify). | |
// 3. Add preProcessorOptions. | |
function getStyleLoaders (cssOptions, preProcessor, preProcessorOptions) { // [3] | |
const loaders = [ | |
isEnvDevelopment && require.resolve('style-loader'), | |
isEnvProduction && { | |
loader: MiniCssExtractPlugin.loader, | |
// css is located in `static/css`, use '../../' to locate index.html folder | |
// in production `paths.publicUrlOrPath` can be a relative path | |
options: paths.publicUrlOrPath.startsWith('.') | |
? { publicPath: '../../' } | |
: {} | |
}, | |
{ | |
loader: require.resolve('css-loader'), | |
options: cssOptions | |
}, | |
{ | |
// Options for PostCSS as we reference these options twice | |
// Adds vendor prefixing based on your specified browser support in | |
// package.json | |
loader: require.resolve('postcss-loader'), | |
options: { | |
// Necessary for external CSS imports to work | |
// https://github.com/facebook/create-react-app/issues/2677 | |
ident: 'postcss', | |
plugins: () => [ | |
require('postcss-flexbugs-fixes'), | |
require('postcss-preset-env')({ | |
autoprefixer: { | |
flexbox: 'no-2009' | |
}, | |
stage: 3 | |
}), | |
// Adds PostCSS Normalize as the reset css with default options, | |
// so that it honors browserslist config in package.json | |
// which in turn let's users customize the target behavior as per their needs. | |
postcssNormalize() | |
], | |
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment | |
} | |
} | |
].filter(Boolean) | |
if (preProcessor) { | |
loaders.push( | |
{ | |
loader: require.resolve('resolve-url-loader'), | |
options: { | |
sourceMap: isEnvProduction ? shouldUseSourceMap : isEnvDevelopment | |
} | |
}, | |
AntdScssThemePlugin.themify({ // [1] | |
loader: preProcessor, // [2] | |
options: Object.assign({ sourceMap: true }, preProcessorOptions) // [3] | |
}) | |
) | |
} | |
return loaders | |
} | |
// https://github.com/facebook/create-react-app/blob/master/packages/react-dev-utils/getCSSModuleLocalIdent.js | |
// Modifications: | |
// 1. Add the 'less' option. | |
function getCSSModuleLocalIdent ( | |
context, | |
localIdentName, | |
localName, | |
options | |
) { | |
// Use the filename or folder name, based on some uses the index.js / index.module.(css|scss|sass) project style | |
const fileNameOrFolder = context.resourcePath.match( | |
/index\.module\.(css|less|scss|sass)$/ // [1] | |
) | |
? '[folder]' | |
: '[name]' | |
// Create a hash based on a the file location and class name. Will be unique across a project, and close to globally unique. | |
const hash = loaderUtils.getHashDigest( | |
path.posix.relative(context.rootContext, context.resourcePath) + localName, | |
'md5', | |
'base64', | |
5 | |
) | |
// Use loaderUtils to find the file or folder name | |
const className = loaderUtils.interpolateName( | |
context, | |
fileNameOrFolder + '_' + localName + '__' + hash, | |
options | |
) | |
// remove the .module that appears in every classname when based on the file. | |
return className.replace('.module_', '_') | |
} | |
module.exports = [ | |
{ | |
webpack: config => { | |
config.resolve.extensions = [...config.resolve.extensions, '.less'] | |
const themePath = path.join(__dirname, '..', 'src', 'theme.scss') | |
config.plugins = [...config.plugins, new AntdScssThemePlugin(themePath)] | |
const result = withLessLoader(config) | |
return result | |
} | |
}, | |
[ | |
'use-babel-config', | |
{ | |
presets: ['react-app'], | |
plugins: [ | |
[ | |
'import', | |
{ | |
libraryName: 'antd', | |
style: true | |
} | |
] | |
] | |
} | |
] | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment