react多項目多模塊運行/打包

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文件夾,存放模塊文件

在模塊、模板目錄,創建兩個項目(文件夾):beijingtianjin

<pre> template - beijing - tianjin src - models - beijing - tianjin </pre>

  • src下的 pages 複製到項目文件夾
  • public下的 index.htmlstatic複製到模板文件夾

注意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.svgsrc/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.jsonnode_modules也是共享的
  • 方便管理,也不用創建那麼多git倉庫了

我這的java項目集成的是FreeMarker,複製對應的項目模板index.html後綴改成.ftl

每次前端打包對應的環境配置之後,把dist目錄的文件同步到java項目的static目錄

這套配置目前管理着超過10個可視化大屏項目,比一個大屏創建一個React方便多了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章