zoukankan      html  css  js  c++  java
  • 【转】搭建 vue2 vue-router2 webpack3 多入口工程

    本文主要介绍如何在此基础上来改造为多入口。

    多入口指的是 webpack 配置项 entry 配置为包含多个 key 的数组或者对象,即 MPA(multiple entry points),那么什么情况下会配置多入口?一般用 vue 大部分是做 SPA(one entry point),因为 SPA 能更好的配合 vue-router,那么我个人想到了几个可能的场景,下面将结合设想的场景来说明如何配置。

    Github地址:https://github.com/qinshenxue/vue2-vue-router2-webpack2

    场景一

    前台页面和后台管理页面都放在一起,目录结构如下(在《从零搭建 vue2 vue-router2 webpack3 工程》的工程目录上改造)。

    mpa1
    |---- build
    |---- src
          |---- admin   // 后台管理
          |     |---- views
          |     |---- app.vue
          |     |---- main.js
          |     |---- router.js
          |
          |---- web     // 移动端
                |---- views
                |---- app.vue
                |---- main.js
                |---- router.js
    

    当然也可以认为就是两个独立的模块,各自都有一套前端路由,只是模块之间存在很多公共的第三方库。对于这种结构,我们希望最终生产构建能够达到以下目标:

    1. web 和 admin 都公用的模块(比如:vue,vue-router,axios等)打包为 vendor.js,另外提取 vendor.js 中的 webpack 模块加载代码为 manifest.js;
    2. web 和 admin 各自引入的第三方库分别打包成 web-vendor.js 和 admin-vendor.js;
    3. web 和 admin 各自业务代码分别打包成 web.js 和 admin.js;
    4. web 和 admin 各自引入的第三方库的 css 分别打包成 web-vendor.css 和 admin-vendor.css;
    5. web 和 admin 各自的 css 代码分别打包成 web.css,admin.css;
    6. 分别生成 web 和 admin 的页面(index.html),页面相应的引入依赖的 css 和 js。

    上述目标用目录表示如下。

    mpa1
    |---- src
    |---- dist
          |---- web
          |     |---- index.html 
          |
          |---- admin
          |     |---- index.html 
          |
          |---- assets
                |---- js
                |     |---- manifest.js
                |     |---- vendor.js
                |     |---- web-vendor.js
                |     |---- admin-vendor.js
                |     |---- web.js
                |     |---- admin.js
                |
                |---- css
                      |---- web-vendor.css
                      |---- admin-vendor.css
                      |---- web.css
                      |---- admin.css 
    

      

    下面开始一步一步调整配置,最终达成上面所有的目标。

    添加入口

    首先当然要在 webpack.base.config.js 添加 web 和 admin 的入口。

    entry: {
        web: path.resolve(__dirname, '../src/web/main.js'),
        admin: path.resolve(__dirname, '../src/admin/main.js')
    }
    

      

    JS 提取配置

    无论是提取各个入口的公共模块(例如 vue、vue-router ),还是提取 web 和 admin 各自引入的第三方库,都只需要用 webpack 自带的插件 webpack.optimize.CommonsChunkPlugin。

    先将 web 和 admin 各自引入的第三方模块提取到 vendor。

    [
        new webpack.optimize.CommonsChunkPlugin({
            name: 'web-vendor',
            chunks: ['web'],
            minChunks: function (module) {
                return module.context && module.context.indexOf("node_modules") !== -1;
            }
        }),
    
        new webpack.optimize.CommonsChunkPlugin({
            name: 'admin-vendor',
            chunks: ['admin'],
            minChunks: function (module) {
                return module.context && module.context.indexOf("node_modules") !== -1;
            }
        })
    ]
    

      接着将 web-vendor 和 admin-vendor 中公共的模块提取为 vendor。

    [
        // ...
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            chunks: ['admin-vendor', 'web-vendor']
        })
    ]
    

      最后提取 vendor 中的 webpack 模块加载部分的代码。

    [
        // ...
        new webpack.optimize.CommonsChunkPlugin({
            name: 'manifest',
            chunks: ['vendor']
        })
    ]
    

      

    CSS 提取配置

    CSS 提取采用 extract-text-webpack-plugin 插件。但是配置不需要那么复杂。

    [
        new ExtractTextPlugin({
            allChunks: true,
            filename: "css/[name].css?[contenthash:8]"
        })
    ]
    

      

    那么如何提取 web 和 admin 引入的第三方库的 CSS 呢?其实在上面配置 web-vendor 和 admin-vendor 的时候就完成了。

    生成入口首页

    生成页面采用 html-webpack-plugin。不同于单入口,需要手动配置 chunks,chunks 配置每个入口依赖的“模块”(chunk)。

    [
        new HtmlWebpackPlugin({
            filename: path.resolve(__dirname, `../dist/web/index.html`),
            template: 'index.tpl.html',
            chunks: ['manifest', 'vendor', 'web-vendor', 'web'],
            inject: true
        }),
        new HtmlWebpackPlugin({
            filename: path.resolve(__dirname, `../dist/admin/index.html`),
            template: 'index.tpl.html',
            chunks: ['manifest', 'vendor', 'admin-vendor', 'admin'],
            inject: true
        })
    ]
    

      

    以上就是所有的配置,满足了所有我们希望达到的构建目标。可以 git clone 文章开头给出的 github 地址尝试一下,注意要切换到分支 mpa1

    场景二

    不用端路由,采用后端路由,页面可能是 php、jsp、aspx,实际开发中这种情况也比较多。这种有点像使用了常用模块加载库(seajs,requirejs)一样,每个页面都需要引入自己的依赖项。目录结构如下。

    mpa2
    |---- build
    |---- src
          |---- css
          |---- images
          |---- pages
                |---- moduleA
                |     |---- index.vue
                |     |---- index.js
                |
                |---- moduleB
                |     |---- index.vue
                |     |---- index.js
                |
                |---- moduleC
                      |---- index.vue
                      |---- index.js
    

      

    对于这种结构,构建目标和场景一类似,具体如下。

    1. 各个模块引入的第三方库打包成 vendor.js,另外提取 vendor.js 中的 webpack 模块加载代码为 manifest.js;
    2. 各个模块自己的 js 分别打包成 moduleA.js、moduleB.js、moduleC.js;
    3. 各个模块引入的第三方库的 css 打包成 vendor.css;
    4. 各个模块自己的 css 分别打包成 moduleA.css、moduleB.css、moduleC.css;
    5. 分别生成各个模块页面(index.html),页面相应的引入依赖的 css 和 js。

    添加入口

    entry: {
        moduleA: resolve('../src/pages/moduleA/index.js'),
        moduleB: resolve('../src/pages/moduleB/index.js'),
        moduleC: resolve('../src/pages/moduleC/index.js')
    }
    

      

    当你模块特别多的时候,这样写肯定不好维护,可以自己写一个函数来生成。

    JS 提取配置

    [
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            chunks: ['moduleA', 'moduleB', 'moduleC'],
            minChunks: function (module) {
                return module.context && module.context.indexOf("node_modules") !== -1;
            }
        }),
    
        new webpack.optimize.CommonsChunkPlugin({
            name: 'manifest',
            chunks: ['vendor']
        })
    ]
    

      

    css 提取和场景一相同,就不再说明了。

    生成入口首页

    这里我把生成页面的改为函数生成。

    var isProd = process.env.NODE_ENV === "production";
    
    exports.genHtmlPlugins = function () {
    
        var baseWebpackConfig = require('./webpack.base.config');
        var path = require('path')
        var plugins = [];
        Object.keys(baseWebpackConfig.entry).forEach(function (name) {
            plugins.push(
                new HtmlWebpackPlugin({
                    filename: isProd ? path.resolve(__dirname, `../dist/${name}/index.html`) : `${name}/index.html`,
                    template: 'index.tpl.html',
                    chunks: isProd ? ['manifest','vendor', name] : [name],
                    inject: true
                }))
        })
        return plugins
    }
    

      

    上面的函数区分了当前环境,开发环境下,filename 配置为入口名/index.html,对应访问地址为http://localhost:8090/moduleA/,开发模式下也不需要用到 CommonsChunkPlugin,因此 chunks 只有一个,而在生产构建时,需要指定 chunks。

    最终构建后的目录结构如下。

    mpa2
    |---- src
    |---- dist
          |---- moduleA
          |     |---- index.html 
          |
          |---- moduleB
          |     |---- index.html 
          |
          |---- moduleC
          |     |---- index.html 
          |
          |---- assets
                |---- js
                |     |---- manifest.js
                |     |---- vendor.js
                |     |---- moduleA.js
                |     |---- moduleB.js
                |     |---- moduleC.js
                |
                |---- css
                      |---- vendor.css
                      |---- moduleA.css
                      |---- moduleB.css
                      |---- moduleC.css  
    

      

    总结

    上述两个场景的配置大同小异,实际上就是通过 CommonsChunkPlugin 和 HtmlWebpackPlugin 这两个插件来完成你想要的目标。

  • 相关阅读:
    [css]display: table-cell,用div做分列布局
    [css]《CSS知多少》
    关于安装Android Studio的一些问题的解决方法
    枚举
    揭开计算机的神秘面纱
    Android模拟器访问本地Web应用
    Android开发中常用的Eclipse快捷键
    详解Windows平台搭建Androiod开发环境
    Web 应用的安全性
    坚持才能成功------王健林
  • 原文地址:https://www.cnblogs.com/Abner5/p/7815259.html
Copyright © 2011-2022 走看看