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
<pre> src - components - pages </pre>
三、目錄改造
分模塊打包:一個模塊就是一個項目,各個模塊獨立配置
- 在根目錄新增
template
文件夾,存放模塊模板文件 - 在
src
目錄新增models
文件夾,存放模塊文件
在模塊、模板目錄,創建兩個項目(文件夾):
beijing
、tianjin
<pre> template - beijing - tianjin src - models - beijing - tianjin </pre>
- 把
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方便多了