多页面应用的前端架构

前提

  • 数据管理平台包含了多个后台项目,后台项目均使用vue作为开发框架。
  • 子项目存在公共头部,需要统一管理维护。
  • 子项目存在公共的依赖(如vuevuexvue-router等),公共依赖包可以统一维护。
  • 子项目存在公共存在公共的配置文件例如postcss.config.js需要统一维护。

解决方案一

在一个项目中,使用 entry配置多个html文件来实现多页面应用

存在的利弊:

  • 配置简单
  • 打包效率低下
  • 灵活性差
  • 需要维护多个html文件

解决方案二(采用)

使用 thinkjs统一维护每个项目的 template.html,并为头部注入用户信息,并且单独构建一个 common项目,统一维护第三方依赖。

存在的利弊:

  • 配置繁琐
  • 打包效率高
  • 灵活性好
  • 只需维护一个html文件

项目目录

├─src
│  ├─bootstrap
│  ├─config
│  ├─controller
│  ├─logic
│  └─model
├─view
│  └─index                            //模板文件目录
└─vue_project                                
    |—package.json                    //统一维护所有依赖
    ├─asset_manage                    //子项目目录
    ├─common                        //打包公共组件项目
    ├─postcss.config.js             //公用的配置文件

配置介绍

common配置介绍

打包主要配置介绍:

插件 描述
webpack.DllPlugin vendor依赖中的库、文件打包(依赖的库取的是package.dependencies的值)
extract-text-webpack-plugin css单独提取出来,打包成一个.css文件
assets-webpack-plugin webpack.DllPlugin打包生成的文件的文件名保存为一个.json文件。方便子项目引用。
optimize-css-assets-webpack-plugin 压缩打包后的.css文件
module.exports = {
    mode: 'production',
    entry: {
        vendor: [...Object.keys(package.dependencies), './css/element-css/index.css', './css/index.postcss'],
    },
    devtool: "source-map",
    output: {
        path: path.join(__dirname, '../vendor'),
        filename: 'dll.[name]_[hash:6].js',
        library: '[name]_[hash:6]'
    },
    module: {
        rules: [{
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: 'css-loader'
                })
            },
            {
                test: /\.postcss$/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: [{
                        loader: 'css-loader',
                        options: {
                            importLoaders: 1
                        }
                    }, 'postcss-loader', ]
                })
            },
            {
                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
                use: 'url-loader'
            },
        ]
    },
    plugins: [
        new webpack.DllPlugin({
            path: path.join(__dirname, '../vendor', '[name]-manifest.json'),
            name: '[name]_[hash:6]',
            context: path.join(__dirname, '../../'), // 执行的上下文环境,对之后DllReferencePlugin有用
        }),
        new ExtractTextPlugin('[name]_[hash:6].css'),
        new AssetsPlugin({
            filename: 'bundle-config.json',
            path: path.join(__dirname, '../vendor')
        }),
        new OptimizeCssAssetsPlugin({
            assetNameRegExp: /\.css$/g,
            cssProcessor: require('cssnano'),
            cssProcessorOptions: {
                parser: require('postcss-safe-parser'),
                discardComments: {
                    removeAll: true
                },
            },
            canPrint: true
        })
    ]
}

vue-cli3配置介绍

vue-cli3的配置文件被封装在了npm模块 @vue/cli-service 中可使用 vue inspect > output.js进行查看
插件 描述
webpack.DllReferencePlugin 将第三方依赖的索引id与对应的第三方依赖具体位置告知webpack
add-asset-html-webpack-plugin common中生成的bundle-config.json文件中的依赖文件注入html-webpack-plugin的模板中
const webpackConfig = {
    configureWebpack: {
        plugins: [
            new webpack.DllReferencePlugin({
                context: path.join(__dirname, '../../'),
                manifest
            }),
            new AddAssetHtmlPlugin([{
                    filepath: require.resolve(`../vendor/${bundleConfig.vendor.js}`),
                    includeSourcemap: false
                },
                {
                    typeOfAsset: 'css',
                    filepath: require.resolve(`../vendor/${bundleConfig.vendor.css}`),
                    includeSourcemap: false
                }
            ])
        ]
    },
    chainWebpack: config => {
        config.resolve.alias.store.delete('vue$');
        config.plugin('copy').tap(args => {
            args[0][0].from = './public';
            args[0][0].to = 'public';
            args[0][0].ignore = ['.*'];
            return args;
        });
        config.plugin('define').tap(args => {
            args[0]['process.env']['BUILD_ENV'] = "'" + process.env.BUILD_ENV + "'";
            return args;
        });
        config.module.rule('postcss').oneOf('vue').use('postcss').loader('postcss-loader').options({
            config: {
                path: path.join(__dirname, '../../')
            }
        });
    },
}

依赖统一管理

如果各自项目的打包依赖分布在各自项目中,依然会增加维护成本以及依赖安装的打包成本

这里就需要理解node查找依赖的逻辑。通过module.paths可以看到node查找依赖时的,顺序

[ 'E:\\datamanagement\\vue_project\\asset_manage\\repl\\node_modules',
  'E:\\datamanagement\\vue_project\\asset_manage\\node_modules',
  'E:\\datamanagement\\vue_project\\node_modules',
  'E:\\datamanagement\\node_modules',
  'E:\\node_modules',
  'C:\\Users\\18044854\\.node_modules',
  'C:\\Users\\18044854\\.node_libraries',
  'C:\\Program Files\\nodejs\\lib\\node' ]

node会从当前目录的node_modules一级一级的向上查找,
所以我们只需要将所有依赖安装在common和vue的父级目录即可

你可能感兴趣的:(多页面应用的前端架构)