简体   繁体   English

将React组件拆分为小部件

[英]Splitting out react components as widgets

I'm trying to create JS widgets from my existing react app. 我正在尝试从现有的React应用程序创建JS小部件。 So currently I have an app that looks something like this 所以目前我有一个看起来像这样的应用

-src 
  - config
  - components
  - containers
  - lib
  - assets
  - widgets
    - widgetOne
    - widgetTwo
      - components
      - widget.js
      - index.js
  - index.js
  - index.html

So, I want directories in the widgets directories to be self contained apps that I can break out into a separate js file and a client can just add the js script into their page in a script tag. 因此,我希望小部件目录中的目录是独立的应用程序,可以将其分解为一个单独的js文件,而客户端只需将js脚本添加到脚本标签中的页面中即可。

I've come close but still facing a few issues. 我已经接近了,但仍然面临一些问题。 Also, I wanted to see if someone had experience doing this following a better pattern. 另外,我想看看是否有人有按照更好的模式进行此操作的经验。

Right now I'm using webpack to do this splitting. 现在,我正在使用webpack进行拆分。 I'm just defining /src/widgets/widgetOne/index.js as an entry point and perfectly creates a separate file. 我只是将/src/widgets/widgetOne/index.js定义为入口点,并完美地创建了一个单独的文件。

Here is my webpack: 这是我的webpack:

const appConstants = function() {
    switch (process.env.NODE_ENV) {
        case 'local':
            const localConfig = require('./config/local');
            return localConfig.config();
        case 'development':
            const devConfig = require('./config/development');
            return devConfig.config();
        case 'production':
        default:
            const prodConfig = require('./config/production');
            return prodConfig.config();
    }
};

const HtmlWebPackPlugin = require("html-webpack-plugin");
const webpack = require('webpack');

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const htmlWebpackPlugin = new HtmlWebPackPlugin({
    template: "./src/index.html",
    filename: "./index.html",
    hash: true
});

let webpackConfig = {
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            },
            {
                test: /\.css$/,
                exclude: [ /assets/, /node_modules/ ],
                use: [
                    {
                        loader: "style-loader"
                    },
                    {
                        loader: "css-loader",
                        options: {
                            modules: true,
                            importLoaders: 1,
                            localIdentName: "[name]_[local]_[hash:base64]",
                            sourceMap: true,
                            minimize: true
                        }
                    }
                ]
            },
            {
                test: /\.(pdf|jpg|png|gif|svg|ico)$/,
                exclude: [/node_modules/],
                use: [
                    {
                        loader: 'file-loader'
                    },
                ]
            },
            {
                test: /\.(woff|woff2|eot|ttf|svg)$/,
                exclude: [/node_modules/],
                use: {
                    loader: 'url-loader?limit100000'
                }
            }
        ]
    },
    entry: {
        main: [ "@babel/polyfill", "./src/index.js"],
        widgetOne: ["./src/widgets/widgetOne/index.js"]
    },
    output: {
        publicPath: appConstants().BASENAME ? JSON.parse(appConstants().BASENAME) : '/'
    }, 
    optimization: {
        splitChunks: {
            chunks: 'all'
        }
    },
    plugins: [
        htmlWebpackPlugin,
        new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /en/),
        new BundleAnalyzerPlugin({
            analyzerMode: 'disabled',
            generateStatsFile: true,
            statsOptions: { source: false }
        }),
        new webpack.DefinePlugin({
            'process.env': appConstants()
        }),
        new webpack.EnvironmentPlugin(['NODE_ENV'])
    ],
    devServer: {
        historyApiFallback: true,
        port: 9090
    }
};

module.exports = webpackConfig;

The problem I have now is while I get the widgetOne.js : 我现在遇到的问题是当我获取widgetOne.js
1) I end up with a vendor~widgetOne.js file that I also need to include to make the widgetOne app to work. 1)我最终得到了一个vendor〜widgetOne.js文件,我还需要包含该文件才能使widgetOne应用程序正常工作。
2) The widgetOne.js also gets added to my index.html file for my main app which I do not want. 2) widgetOne.js也被添加到我不需要的主应用程序的index.html文件中。

Is there a way to configure webpack properly to make this work? 有没有一种方法可以正确配置webpack来使其工作?

So, this is the solution I came up with that seems to work. 因此,这是我想出的可行的解决方案。 I still don't know if this is the best approach but it' the only one I was able to get to work for me. 我仍然不知道这是否是最好的方法,但这是我唯一能够为我工作的方法。

I decided to build the widgets as a different environment process and and modify the webpack configs based on that environment. 我决定将小部件构建为不同的环境过程,并根据该环境修改webpack配置。

So the package.json I add this line under scritps: 所以package.json我在scritps下添加了这一行:
"build-widgets": "cross-env NODE_ENV=plugins webpack --mode development",

And I added this section to the end of my webpack.config.js file: 我将这一节添加到了webpack.config.js文件的末尾:

// Override webpack configs when building plugins
if ( process.env.NODE_ENV === 'plugins') {
    webpackConfig.entry = {
       widgetOne: [ "@babel/polyfill", "./src/plugins/widgetOne/index.js"]
    }
    webpackConfig.output = {
    publicPath: appConstants().DS_BASENAME ? JSON.parse(appConstants().DS_BASENAME) : '/',
        path: __dirname + '/dist/widgets',
        library: 'MyApp',
        libraryTarget: 'umd',
        umdNamedDefine: true
   }
}

Alternatively, I could have just added a second webpack.config.js exclusively to deal with my widgets build. 或者,我可以只添加第二个webpack.config.js来处理我的小部件构建。 In my case I didn't feel the need for it just yet but it's something to be considered for sure, just for the sake of keeping configs separate. 在我的情况下,我还没有感觉到需要它,但是为了将配置分开,这是可以肯定考虑的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM