本文以vue-cli3+为例,实现多系统集成下的分模块打包。分模块打包方式多种多样,下文可适用于多系统之间互不干扰,主系统可集成各子系统,各子系统又可单独运行的业务场景。

一、目标

我们要实现什么?所谓分模块打包,那么各个模块内就必须得有自己独立的入口文件,路由文件。按照这种构想,我在一个新的脚手架src目录下新建了一个projects目录:

vue node modules打包 vue按模块打包_vue

如上图,可以看到Aproject、B、C、D四个项目。我在A项目中建了assets,common和views文件夹,其中assets可以再建img和css的文件夹,common内可以放公共组件或者方法,views页面可以放页面,甚至你还可以建一个components文件夹专门用来放组件。

好了,我们的视图目录结构大概就是上面的样子。我们期待的是,我们可以打包这个A模块这个‘小vue',就像打包一个完整vue的项目一样。那么如何实现这部分呢?

二、打包单个模块

我们知道,在package.json中,有项目启动,打包的命令。

vue node modules打包 vue按模块打包_css_02

我们可以从这里入手。

这里就不得不提到cross-env这个模块了。
我们之前在设置生产环境,测试环境,开发环境时也会用到这个模块。在这里不详细表述了。

cross-env:npm install --save-dev cross-env


现在我们的思路大概是这样的,当我们执行打包命令的时候,通过cross-env去找到我们的入口文件,然后再打包。

所以我们可以模仿环境变量的写法,在package中写入如下图代码。

vue node modules打包 vue按模块打包_html_03

代码:

"dev:projectA": "cross-env PROJECT_NAME=projectA vue-cli-service serve",
"dev:projectB": "cross-env PROJECT_NAME=projectB vue-cli-service serve",
"dev:projectC": "cross-env PROJECT_NAME=projectC vue-cli-service serve",
"dev:projectD": "cross-env PROJECT_NAME=projectD vue-cli-service serve",
"build:projectA": "cross-env PROJECT_NAME=projectA vue-cli-service build",
"build:projectB": "cross-env PROJECT_NAME=projectB vue-cli-service build",
"build:projectC": "cross-env PROJECT_NAME=projectC vue-cli-service build",
"build:projectD": "cross-env PROJECT_NAME=projectD vue-cli-service build",


写完了这些,我们就可以着手模仿vue配置小vue的文件了。

在main.js中配置如下代码:

import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
 
Vue.config.productionTip = false;
 
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");


在App.vue中配置如下代码:

<template>
<div id="app">
<router-view />
</div>
</template>
 
<style lang="less">
 
</style>


在router.js中配置如下代码

import Vue from "vue";
import Router from "vue-router";
import Home from "./views/Home.vue";
 
Vue.use(Router);
 
export default new Router({
routes: [
{
path: "/",
name: "home",
component: Home
}
]
});


在page文件夹中建立Home.vue,写入如下代码:

<template>
<div>
我是a项目
</div>
</template>
 
<script>
export default {};
</script>
 
<style></style>


在项目最外层建立config文件夹,在其中新建projectsConfig.js写入:

const config = {
projectA: {
pages: {
index: {
entry: "src/projects/projectA/main.js",
template: "public/index.html",
filename: "index.html"
}
},
devServer: {
port: 8080, // 端口地址
open: false, // 是否自动打开浏览器页面
host: "0.0.0.0", // 指定使用一个 host,默认是 localhost
https: false, // 使用https提供服务
disableHostCheck: true,
// 设置代理
proxy: {
"/eopenhapi": {
target: "http://open.jdpay.com",
changeOrigin: true
},
"/hapi": {
target: "http://open.jdpay.com",
changeOrigin: true
}
}
}
},
projectB: {},
projectC: {}
};
module.exports = config;


把projectsConfig.js并入vue.config.js,vue.config.js中代码如下

const config = require("./config/projectsConfig.js");
let projectName = process.env.PROJECT_NAME;

module.exports = {
...config[projectName],
// pages: conf.pages,

// 基本路径
// baseUrl: './',//vue-cli3.3以下版本使用
publicPath: "./", // vue-cli3.3+新版本使用

// 输出文件目录
outputDir: "dist/" + projectName + "/"
};


写到这里我们就建立一个完整的小vue了。

运行命令 cnpm run dev:projectA


2. 把css、js打包进HTML 


module.exports={
  publicPath: './',//使用相对路径
  productionSourceMap: false,
  // publicPath:"./",  // 可以设置成相对路径,这样所有的资源都会被链接为相对路径,打出来的包可以被部署在任意路径
  outputDir:"dist",  //打包时生成的生产环境构建文件的目录
  chainWebpack: config => {
    config.plugin('preload')
      .tap(args => {
        args[0].fileBlacklist.push(/\.css/, /\.js/)
        return args
      })
    config.plugin('inline-source')
      .use(require('html-webpack-inline-source-plugin'))
    config
      .plugin('html')
      .tap(args => {
        args[0].title = 'JSON和PHP Array 互转'
        args[0].inlineSource = '(\.css|\.js$)'
        return args
      })
  }
}


3. 如果想要在分模块的文件里,也要把css、js打包进单独HTML文件,则以下地方要做一下小改动

  • 插件版本
  • "html-webpack-plugin": "^4.4.1",
  • "html-webpack-inline-source-plugin": "^0.0.10",
  • 配置修改
  • const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin')
chainWebpack: config => {

        config.plugin('preload-index')   // 不分模块这里是preload,分模块就是preload-index

        .tap(args => {

          args[0].fileBlacklist.push(/\.css/, /\.js/)

          return args

        })

   

      config.plugin('inline-source')

        .use(HtmlWebpackInlineSourcePlugin)

      config

        .plugin('html-index')  // 不分模块这里是html,分模块就是html-index

        .tap(args => {

          args[0].inlineSource = '(\.css|\.js$)'

          return args

        })

 }