1

我已经构建了一个 spa react 应用程序,下面是该应用程序的 index.html

有 2 个应用程序,app1 和 app2,app1 最初加载,app2 仅在需要时加载

index.html 用于 app1 和 app2 的单个 spa 配置

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=9;IE=10;IE=Edge,chrome=1" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>Project</title>

    <!-- app2 css -->
    <link href='http://localhost:8003/app2.css' rel='stylesheet'/>
</head>

<body>
    <script>

     function randstr(prefix) {
       return Math.random().toString(36).replace('0.', prefix || '');
     }
     var suffix = randstr('?v=');
      document.write('<script src="config/config.js' + suffix + '"><\/script>');
      document.write('<script type="systemjs-importmap" crossorigin="anonymous">' +
      '{ \n"imports": {\n' +
      ' "@portal/config": "http://localhost:8001/index.js'  + '",\n' +
      ' "@portal/app1": "http://localhost:8002/app1.js'  + '",\n' + // this loads first, it has login page
      ' "@portal/app2": "http://localhost:8003/app2.js'  + '" \n }\n}' + // app 2 which loads on click
      '<\/script>');

    </script>

    <!-- load the vendor chunk of app2-->
    <script src='http://localhost:8003/vendor.app2.js'></script>

    <!-- Load the common deps-->
    <script> 
       imports and loads dependencies of react, react-dom, lodash and others   
    </script>
    
    <!-- Load the application -->
    <script>
      SystemJS.import('@portal/config')
    </script>

    <div id="app" class="site-container"></div>

</body>

</html>

在上面的 index.html 中,通过 systemjs-importmap 配置了应用程序,一切正常。

正如您在 importmap 中看到的,导入 app2("@portal/app2": "http://localhost:8003/app2.js'),这只会在需要时加载,但这个包有点大,我有试图通过提取css和供应商块来提高性能,缩小js和css,这确实提高了性能,这些脚本也被添加了(http://localhost:8003/vendor.app2.js,http://本地主机:8003/app2.css)

app2 的 webpack.config.js

const webpack = require('webpack')
const path = require('path')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const TerserPlugin = require("terser-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  entry: path.resolve(__dirname, 'src/app2.js'),
  output: {
    filename: 'app2.js',
    library: 'app2',
    libraryTarget: 'amd',
    path: path.resolve(__dirname, 'build/app2'),
  },
  mode: 'production',
  module: {
    rules: [
      {parser: {System: false}},
      {
        test: /\.js$/,
        exclude: [path.resolve(__dirname, 'node_modules')],
        loader: 'babel-loader',
        options: {
          presets: ["@babel/preset-env"]
        }
      },
      {
        test: /\.krem.css$/,
        exclude: [path.resolve(__dirname, 'node_modules')],
        use: [
          {
            loader: 'kremling-loader',
            options: {
              namespace: 'app2',
              postcss: {
                plugins: {
                  'autoprefixer': {},
                },
              },
            },
          },
        ],
      },
      { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader' },
      { test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'url-loader' },
    //   { test: /\.css$/, loader: "style-loader!css-loader"},
      { test: /\.css$/, use: [
        MiniCssExtractPlugin.loader,
        'css-loader',
      ]},
    ],
  },
  plugins: [
    new CleanWebpackPlugin({
      verbose: true,
      cleanOnceBeforeBuildPatterns: [path.resolve(__dirname, 'build/app2')],
    }),
    new CopyWebpackPlugin({
      patterns: [
        {from: path.resolve(__dirname, 'src/ppsr.js')},
      ]}),
    new TerserPlugin({
              parallel: true,
              cache: true
      }),
    new MiniCssExtractPlugin({
        filename: '[name].css',
      }),
    new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
  ],
  optimization: {
    splitChunks: {
        cacheGroups: {
            vendor: {
                name: 'vendor',
                chunks: 'all',
                reuseExistingChunk: true,
                priority: 1,
                test: module =>
                /[\\/]node_modules[\\/]/.test(module.context),
                minChunks: 1,
                minSize: 0,
            },
        },
    },
    minimize: true,
    minimizer: [
        new CssMinimizerPlugin(),
      ],
},
  devtool: 'source-map',
  externals: [
    /^@portal\/*/,
    /^lodash$/,
    /^single-spa$/,
    /^rxjs\/?.*$/,
    /^react$/,
    /^react\/lib.*/,
    /^react-dom$/,
    /.*react-dom.*/,
  ],
}

我得到了构建文件 vendor.app2.css、app2.css、app2.js 文件...仅在需要时加载 js,因为它是由 importmap 导入的,并且 css 和供应商位于全局空间中(意味着加载与 app2 无关加载与否)

问题: 如何仅在单个 spa 反应中需要时加载与 app2 的 js 相同的供应商和 CSS?

4

0 回答 0