react多项目多模块运行/打包
react17
为例,实现多项目的分模块打包。多项目之间共享组件和依赖,运行、打包互不干扰。
一、安装
npm install -g create-react-app
# OR
yarn global add create-react-app
二、创建项目:
create-react-app my-project
src
目录新增pages
文件夹,除index.js
以外的文件都移到pages
src
目录新增components
文件夹,创建HelloWorld
组件并引入到App.js
src - components - pages
三、目录改造
分模块打包:一个模块就是一个项目,各个模块独立配置
- 在根目录新增
template
文件夹,存放模块模板文件 - 在
src
目录新增models
文件夹,存放模块文件
在模块、模板目录,创建两个项目(文件夹):
beijing
、tianjin
template - beijing - tianjin src - models - beijing - tianjin
- 把
src
下的pages
复制到项目文件夹 - 把
public
下的index.html
、static
复制到模板文件夹
注意
App.js
中图片和组件的路径
四:配置改造
cross-env
是跨平台环境变量的工具,react-app-rewired
是重写配置的工具,新增这俩依赖:
yarn add cross-env react-app-rewired
每个项目都有开发/生产环境,需要新增4个脚本命令:
// package.json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"start:beijing": "cross-env MODEL_NAME=beijing react-app-rewired start",
"build:beijing": "cross-env MODEL_NAME=beijing react-app-rewired build",
"start:tianjin": "cross-env MODEL_NAME=tianjin react-app-rewired start",
"build:tianjin": "cross-env MODEL_NAME=tianjin react-app-rewired build",
"test": "react-app-rewired test"
},
homepage
对应index.html
中的变量%PUBLIC_URL%
,方便打包后预览
// package.json
"homepage":"./",
基本配置:
// config-overrides.js
module.exports = function override(config, env) {
// 输出目录
config.output = {
...config.output,
// publicPath: '',// package.json -> homepage = './'
filename: `static/js/bundle.js`,
chunkFilename: `static/js/[name].chunk.js`,
};
return config;
};
到这一步,最好运行一次默认打包配置,表示新增的目录和文件没有影响默认配置
本例引用了公共的静态资源和组件用于测试:
src/assets/logo.svg
、src/components/HelloWorld.js
如果可以正常打包,接下来就是配置多模块,能想到多模块打包,传统配置必定很熟了,不再赘述,请看注释…
完整配置:
const path = require('path');
const paths = require('react-scripts/config/paths');
const HtmlWebpackPlugin = require('html-webpack-plugin');
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = function (config, env) {
let pathDir = path.join(__dirname, 'dist');
paths.appBuild = path.join(__dirname, 'dist');
if (process.env.MODEL_NAME) {
let mName = process.env.MODEL_NAME;
// 输出目录
pathDir = resolve(`dist/${mName}`);
paths.appBuild = resolve(`dist/${mName}`);
// 模块入口
// paths.appSrc = resolve(`src`);
// paths.appIndexJs = resolve(`src/index`);
paths.appIndexJs = resolve(`src/models/${mName}/index`);
config.entry = paths.appIndexJs;
// 模板入口
paths.appPublic = resolve(`template/${mName}`);
paths.appHtml = resolve(`template/${mName}/index.html`);
config.plugins = [
...config.plugins,
new HtmlWebpackPlugin({
title: mName,
inject: 'body',
// chunks: ["bundle","main"],
template: paths.appHtml,
filename: 'index.html',
})
];
}
// 关闭 source-map
config.devtool = false;
// 输出目录
config.output = {
...config.output,
path: pathDir,
// publicPath: '', // package.json -> homepage = './'
filename: 'static/js/bundle.js',
chunkFilename: 'static/js/[name].chunk.js',
};
// 外部扩展
config.externals = {
'react': 'React',
'react-dom': 'ReactDOM'
};
// 设置别名
config.resolve = {
...config.resolve,
alias: {
...config.alias,
'@': path.resolve(__dirname, 'src'),
},
};
return config;
};
这样做的好处:
- 不用每次都这样
create-react-app my-project
- 共享组件、共享静态资源
- 节省磁盘,
package.json
、node_modules
也是共享的 - 方便管理,也不用创建那么多
git
仓库了
我这的java
项目集成的是FreeMarker
,复制对应的项目模板index.html
后缀改成.ftl
每次前端打包对应的环境配置之后,把dist
目录的文件同步到java
项目的static
目录
这套配置目前管理着超过10个可视化大屏项目,比一个大屏创建一个React方便多了