【轉】搭建 vue2 vue-router2 webpack3 多入口工程

本文主要介紹如何在此基礎上來改造爲多入口。php

多入口指的是 webpack 配置項 entry 配置爲包含多個 key 的數組或者對象,即 MPA(multiple entry points),那麼什麼狀況下會配置多入口?通常用 vue 大部分是作 SPA(one entry point),由於 SPA 能更好的配合 vue-router,那麼我我的想到了幾個可能的場景,下面將結合設想的場景來講明如何配置。css

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

場景一

前臺頁面和後臺管理頁面都放在一塊兒,目錄結構以下(在《從零搭建 vue2 vue-router2 webpack3 工程》的工程目錄上改造)。前端

mpa1
|---- build
|---- src
      |---- admin   // 後臺管理
      |     |---- views
      |     |---- app.vue
      |     |---- main.js
      |     |---- router.js
      |
      |---- web     // 移動端
            |---- views
            |---- app.vue
            |---- main.js
            |---- router.js

固然也能夠認爲就是兩個獨立的模塊,各自都有一套前端路由,只是模塊之間存在不少公共的第三方庫。對於這種結構,咱們但願最終生產構建可以達到如下目標:vue

  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。

上述目標用目錄表示以下。node

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

添加入口

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

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。git

先將 web 和 admin 各自引入的第三方模塊提取到 vendor。github

[
    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 這兩個插件來完成你想要的目標。

相關文章
相關標籤/搜索