如何构建多个反应应用程序并仍然共享代码+资产

时间:2017-10-16 09:34:31

标签: reactjs webpack

我已经构建了一个使用以下结构的反应应用程序;

node_modules
src/
  app/
    index.ts
    index.html
    ...
  server/
    index.ts
    ...
  node_modules/ // using the Alle pattern here
    @<custom_packages>
      api
      components

现在我需要添加一个新应用。哪个运行在不同的域上,但应该能够使用尽可能多的共享代码,包括我们的自定义包。我的第一次尝试是做以下事情;

node_modules
src/
  app1/
    index.ts
    index.html
    ...
  app2/
    index.ts
    index.html
    ...
  server/
    index.ts // Uses ENV_VAR to serve a different bundle
    ...
  node_modules/
    @<custom_packages>
      api
      components

我现在遇到的问题是两个应用都会生成自己的资产等。但我想在应用之间共享它们,以便客户端可以缓存它们。我可以决定不使用webpack来构建资产,只是将它们放在一个静态文件夹中,但后来我失去了webpack中offline-plugin的支持。

在这种情况下,我们也决定使用mono-repo。这使得CI变得更加困难,但管理共享代码要容易得多。我有点想知道是否有经验丰富的开发人员更经常遇到这种情况。

基本上,你如何构建2应用程序应该尽可能多地共享代码?

1 个答案:

答案 0 :(得分:0)

我需要类似的设置但是对于Angular。这是我的Webpack配置(我只留下相关部分):

const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const apps = [
  {
    name: 'app1',
    baseUrl: '/app1'
  },
  {
    name: 'app2',
    baseUrl: '/app2'
  }
];

module.exports = function (args = {}) {
  const isDev = !args.PROD;
  const distPath = 'dist';

  var config = {};

  config.entry = {};

  apps.forEach(function (app) {
    config.entry[getAppBundleName(app)] = './src/apps/' + app.name + '/main.ts';
  });

  config.output = {
    path: root(distPath),
    filename: '[name].js',
    chunkFilename: '[name].[chunkhash].js',
    publicPath: '/dist/'
  };

  config.resolve = {
    extensions: ['.ts', '.js', '.json'],

    modules: [root('src'), root('node_modules')]
  };

  config.module = {
    rules: [
      // Add your loaders here
    ]
  };

  config.plugins = [
    // Add your plugins here

    // This enables tree shaking of the vendor modules
    new CommonsChunkPlugin({
      name: 'vendor',
      chunks: ['admin'].concat(apps.map(getAppBundleName)),
      minChunks: module => /node_modules/.test(module.resource)
    }),
    new CommonsChunkPlugin({
      name: 'shared',
      chunks: ['admin'].concat(apps.map(getAppBundleName)),
      minChunks: module => /src(\\|\/)shared/.test(module.resource)
    })
  ];

  apps.forEach(function (app) {
    var otherApps = apps.slice();

    var appItemIndex = otherApps.indexOf(app);

    if (appItemIndex > -1) {
      otherApps.splice(appItemIndex, 1);
    }

    config.plugins.push(new HtmlWebpackPlugin({
      template: 'index_template.html',
      title: app.name,
      filename: getAppDevServerHtmlFileName(app),
      excludeChunks: otherApps.map(getAppBundleName),
      chunksSortMode: 'manual',
      chunks: ['vendor', 'shared', getAppBundleName(app)],
      inject: 'head',
      metadata: {
        baseUrl: app.baseUrl
      }
    }));
  });

  config.devServer = {
    port: 4200,
    stats: stats,
    historyApiFallback: {
      rewrites: apps.map(function (app) {
        return {
          from: new RegExp('^' + app.baseUrl),
          to: '/dist/' + getAppDevServerHtmlFileName(app)
        }
      }),
    },
  };

  return config;
}

function getAppBundleName(app) {
  return app.name;
}

function getAppDevServerHtmlFileName(app) {
  return app.name + '_index.html';
}

function root(args) {
  args = Array.prototype.slice.call(arguments, 0);
  return path.join.apply(path, [__dirname].concat(args));
}`

在我的情况下,我有以下文件夹结构,类似于你的:

node_modules
src/
  apps/
    app1/
      ...
      main.ts
    app2/
      ...
      main.ts
  shared/
    shared-module1/
      ...  
    shared-module2/
      ...
    index.ts
  ...
webpack.config.js

以下是dist文件夹中编译后的输出:

dist/
   app1.js
   app1_index.html
   app2.js
   app2_index.html
   vender.js
   shared.js

如您所见,vendor.jsshared.js包含应用之间的共享代码。