riant-scripts
Create your app using create-react-app , and tweak the create-react-app webpack config(s) , especially preset
less-loaderandstylus-loader.
中文文档
Install riant-scripts
$ npm install riant-scripts --save-dev
Schema
/* riant.config.js */
module.exports = {
alias: { instanceof: ['Function', 'Object'] },
babelPlugins: { instanceof: ['Function', 'Array'] },
chainWebpack: { instanceof: 'Function' },
configureWebpack: { instanceof: 'Function' },
css: {
type: 'object',
properties: {
modules: { type: 'boolean' },
sourceMap: { type: 'boolean' },
loaderOptions: {
type: 'object',
properties: {
css: { type: 'object' },
less: { type: 'object' },
stylus: { type: 'object' },
postcss: { type: 'object' }
}
}
}
},
devServer: { instanceof: ['Function', 'Object'] },
extensions: { instanceof: ['Function', 'Array'] },
externals: { instanceof: ['Function', 'Array', 'RegExp', 'Object'] },
filenameHashing: { type: 'boolean' },
jest: { instanceof: ['Function', 'Object'] },
pages: { type: 'object' },
parallel: { type: ['boolean', 'number'] },
paths: { instanceof: ['Function', 'Object'] },
riantPlugins: { instanceof: 'Array' },
useEslintrc: { type: 'boolean' }
}
Create a riant.config.js file in the root directory
- Create aliases to import or require certain modules more easily
/* riant.config.js */
module.exports = {
alias: {
'@': path.join(__dirname, 'src')
}
}
/* riant.config.js */
module.exports = {
alias(chainedMap, env) {
chainedMap.set('@', path.join(__dirname, 'src'));
}
}
- Add plugins to Babel
/* riant.config.js */
module.exports = {
babelPlugins: [
[
'import',
{
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
},
'fix-import-imports'
],
['@babel/plugin-proposal-decorators', { legacy: true }]
]
}
/* riant.config.js */
module.exports = {
babelPlugins(plugins, env) {
plugins.push(
[
'import',
{
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
},
'fix-import-imports'
],
['@babel/plugin-proposal-decorators', { legacy: true }]
);
}
}
/* riant.config.js */
module.exports = {
babelPlugins(plugins, env) {
return plugins.concat([
[
'import',
{
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
},
'fix-import-imports'
],
['@babel/plugin-proposal-decorators', { legacy: true }]
]);
}
}
- Customize Webpack config
/* riant.config.js */
module.exports = {
chainWebpack(chainedConfig, env) {
if (env === 'production') {
// supporting Internet Explorer 9
chainedConfig
.entry('main')
.prepend(require.resolve('react-app-polyfill/stable'))
.prepend(require.resolve('react-app-polyfill/ie9'));
// without `console.log`
chainedConfig.optimization.minimizer('TerserPlugin').init((plugin) => {
plugin.options.terserOptions.compress.pure_funcs = ['console.log'];
return plugin;
});
}
// code splitting
if (env !== 'test') {
chainedConfig
.optimization.splitChunks({
cacheGroups: {
vendors: {
name: `chunk-vendors`,
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: `chunk-common`,
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
});
}
}
}
/* riant.config.js */
module.exports = {
configureWebpack(objectConfig, env) {
if (env === 'production') {
// without `console.log`
objectConfig
.optimization
.minimizer[0]
.options
.terserOptions
.compress
.pure_funcs = ['console.log'];
}
}
}
- Customize style loader options
/* riant.config.js */
module.exports = {
css: {
loaderOptions: {
stylus: {
define: {
'$cdn': 'https://cdn.jsdelivr.net'
}
}
}
}
}
- Customize Dev Server config
/* riant.config.js */
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8088',
changeOrigin: true
}
},
}
}
/* riant.config.js */
module.exports = {
devServer(devConfig, env) {
devConfig.proxy = {
'/api': {
target: 'http://localhost:8088',
changeOrigin: true
}
};
}
}
- Attempt to resolve these extensions in order
/* riant.config.js */
module.exports = {
extensions: ['.properties']
}
/* riant.config.js */
module.exports = {
extensions(chainedSet, env) {
chainedSet.add('.properties');
}
}
- Prevent bundling of certain imported packages and instead retrieve these external dependencies at runtime
/* riant.config.js */
module.exports = {
externals: {
jquery: 'jQuery'
}
}
/* riant.config.js */
module.exports = {
externals() {
return {
jquery: 'jQuery'
};
}
}
- Attempt to remove hash from filename
/* riant.config.js */
module.exports = {
filenameHashing: false
}
- Attempt to update jest config
/* riant.config.js */
module.exports = {
jest(jestConfig) {
return jestConfig;
}
}
- multi-page setup
/* riant.config.js */
module.exports = {
pages: {
home: 'src/home.js',
form: 'src/form.js',
notfound: 'src/notfound.js'
}
}
- Attempt to update paths
/* riant.config.js */
module.exports = {
paths: {
}
}
/* riant.config.js */
module.exports = {
paths(pathsConfig, env) {
}
}
- use thread-loader for Babel or TypeScript transpilation
/* riant.config.js */
module.exports = {
parallel: true
}
- Add progress bar
/* riant.config.js */
module.exports = {
progressBar: true
}
- Add plugins to riant-scripts
/* riant.config.js */
module.exports = {
riantPlugins: [
function (service, projectOptions) {
}
]
}
- Use eslintrc
/* riant.config.js */
module.exports = {
useEslintrc: true
}
Extended Webpack Configuration
- supporting Internet Explorer 9
/* riant.config.js */
module.exports = {
chainWebpack(chainedConfig, env) {
if (env === 'production') {
chainedConfig
.entry('main')
.prepend(require.resolve('react-app-polyfill/stable'))
.prepend(require.resolve('react-app-polyfill/ie9'));
}
}
- without console.log
/* riant.config.js */
module.exports = {
chainWebpack(chainedConfig, env) {
if (env === 'production') {
chainedConfig.optimization
.minimizer('TerserPlugin')
.init((plugin) => {
plugin.options.terserOptions.compress.pure_funcs = ['console.log'];
return plugin;
});
}
}
- code splitting
/* riant.config.js */
module.exports = {
chainWebpack(chainedConfig, env) {
if (env !== 'test') {
chainedConfig.optimization
.splitChunks({
cacheGroups: {
vendors: {
name: `chunk-vendors`,
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: `chunk-common`,
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
});
}
}
Create .env.production file in the root directory
- Set env for production
# Source maps are resource heavy and can cause out of memory issue for large source files.
GENERATE_SOURCEMAP=false
# Some apps do not need the benefits of saving a web request, so not inlining the chunk makes for a smoother build process.
INLINE_RUNTIME_CHUNK=false
IMAGE_INLINE_SIZE_LIMIT=30000
Code Structure
+-- your-project
| +-- riant.config.js
| +-- node_modules
| +-- package.json
| +-- public
| +-- README.md
| +-- src
Use riant-scripts instead of react-scripts in npm scripts of package.json for start、build and test
/* package.json */
"scripts": {
- "start": "react-scripts start",
+ "start": "riant-scripts start",
- "build": "react-scripts build",
+ "build": "riant-scripts build",
- "test": "react-scripts test --env=jsdom",
+ "test": "riant-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
Note: Keep the eject script. That gets run only once for a project, after which you are given full control over the webpack configuration making riant-scripts no longer required.
Start the Dev Server
$ npm start
Build your app
$ npm run build
