Vue-cli 2.X 如何配置多項目集成環(huán)境

本次目標

多模塊集成的 vue 項目识埋,多項目共用一份配置凡伊,可以互相依賴,也可以獨立打包部署窒舟。
所有操作只需要使用不同操作命令即可系忙,如npm run dev:proj1 或者 npm run dev:proj2

使用業(yè)務場景

  1. 如果多個項目使用同一樣式依賴 相同的 js / 組件, 可以每個項目導入一次惠豺,但后期維護時, 公用引用的部分一旦修改就會就牽一發(fā)而動全身银还,所有引用此文件的都得改動,有些繁瑣洁墙。
  2. 如果項目有多個子模塊(同時子模塊之間又存在互相依賴關系)蛹疯;對于這樣的場景是可以把項目獨立發(fā)布到npm倉庫,但是這樣又涉及到每個模塊都需要獨立編譯好再發(fā)布热监,實際過程有顯得有些繁瑣捺弦。

對于以上場景可以使用一個項目管理多個子模塊也是一個不錯的選擇

多頁面 和 多模塊的區(qū)別

多頁面:指一個項目有多個入口,打包是會生成多個html文件孝扛,實際開發(fā)過程中都是混合在一個項目中開發(fā)列吼;
多模塊:是指不同的業(yè)務模塊可以進行拆分;各自獨立運行苦始、也可以互相引用寞钥,這一點和通過npm發(fā)布是類似的;
對于一些項目本身不允許發(fā)布的情況下陌选,既可以獨立開發(fā)理郑,又不需要發(fā)布到共有倉庫;

多模塊優(yōu)點

  1. 高復用性
  2. 統(tǒng)一管理依賴庫
  3. 不同模塊使用的依賴各自按需打包
  4. 模塊之間相互獨立運行、編譯咨油、打包
  5. 模塊之間可以直接互相引用您炉,不需要 iframe

接下來我們看下具體配置步驟~~見證奇跡的時刻

第一步: 把src目錄下的文件換成多模塊的形式

image

項目模塊結構安裝上面的改動完畢之后,控制臺會報一些路徑錯誤之類的:
這是因為webpack.base.conf.js里面的main.js的路徑發(fā)生改變導致的臼勉,
之前項目是單模塊只要一個main.js邻吭,
現(xiàn)在換成多模塊之后每個模塊都有自己獨立的main.js餐弱,故此要修改配置宴霸。

第二步: 增加config/multi.conf.js多模塊配置文件

const path = require('path')
const pack = require('../package.json')
const argvs = process.argv.slice(2)
class MultiModule {
    constructor(multiName, opts) {
        let datetime = Date.now(),
            name = multiName.split('_')[0];
        Object.assign(this, {
            name,
            multiName,
            assetsSubDirectory: 'static',
            assetsPublicPath: '/',
            port: 8080,
            host: '0.0.0.0',
            proxyTable: null,
            entry: {
                app: ['babel-polyfill', `./src/${name}/main.js`]
            },
            alias: resolve(`src/${name}`),
            index: path.resolve(__dirname, `../dist/${name}/index.html`),
            favicon: path.resolve(__dirname, `../src/${name}/assets/favicon.ico`),
            assetsRoot: path.resolve(__dirname, `../dist/${name}/`),
            pubdate: `${name}_v${pack.version}_${datetime}`,
            publics: [name].concat(opts.statics || []),
            deployConfig: null
        }, opts)
    }
}

// 多模塊獨立配置 ==> 所有模塊的入口選擇
var importModules = [
    new MultiModule('proj1', {
        port: 8081,
        statics: ['static1'],
        assetsPublicPath: '/',
        baseUrl: '/api/',
        proxyTable: {
            '/api/': getProxyConfig({ '^/ent': '/' }, 'http://XX.XX.XX.XX')
        }
    }),
    new MultiModule('proj2', {
        port: 8082,
        statics: ['static2'],
        assetsPublicPath: '/',
        baseUrl: '/api/',
        proxyTable: {
            '/api/': getProxyConfig({ '^/ent': '/' }, 'http://XX.XX.XX.XX')
        }
    }),
    new MultiModule('proj3', {
        port: 8083,
        statics: ['static1'],
        assetsPublicPath: '/',
        baseUrl: '/api/',
        proxyTable: {
            '/api/': getProxyConfig({ '^/ent': '/' }, 'http://XX.XX.XX.XX')
        }
    })
]

function resolve(dir) {
    return path.join(__dirname, '..', dir)
}

function getParams(key) {
    let item = argvs.find(item => item.split('=')[0] === key)
    return item ? item.split('=') : []
}

function getModuleAlias() {
    let alias = {}
    importModules.forEach(({ name }) => {
        alias[`@${name}`] = resolve(`src/${name}`)
    })
    return alias
}

function getModuleProcess(name) {
    let mItem = importModules.find(item => item.multiName === name)
    return mItem || importModules[0]
}

function proxyHandle(proxyReq, req, res, options) {
    let origin = `${options.target.protocol}//${options.target.hostname}`
    proxyReq.setHeader('origin', origin)
    proxyReq.setHeader('referer', origin)
}

function onProxyReq(proxyReq, req, res, options) {
    proxyHandle(proxyReq, req, res, options)
}

function onProxyReqWs(proxyReq, req, socket, options, head) {
    proxyHandle(proxyReq, req, socket, options)
}

// 生成代理類
function getProxyConfig(pathRewrite, target, options) {
    return Object.assign({
        target,
        secure: false,
        changeOrigin: true,
        ws: false,
        // cookieDomainRewrite: { '*': '' },
        // cookiePathRewrite: { '*': '/' },
        onProxyReq,
        onProxyReqWs,
        pathRewrite: pathRewrite
    }, options)
}

var lifecycleEvents = String(process.env.npm_lifecycle_event).split(':')
var moduleName = getParams('name')[1] || lifecycleEvents[1]
const multiConfig = {
    modules: importModules,
    moduleAlias: getModuleAlias(),
    process: getModuleProcess(moduleName),
}

module.exports = multiConfig;

第三步:修改build/webpack.base.conf.js文件

  1. 引入新配置 const multiConfig = require('../config/multi.conf')
  2. 修改入口配置 entry: multiConfig.process.entry // 之前為 app: ['babel-polyfill', ./src/${name}/main.js]
  3. 修改資源路徑 publicPath: process.env.ASSETS_PUBLICPATH
  4. 修改
alias: {
    'vue$': 'vue/dist/vue.esm.js',
    '@comm': resolve(`src/comm`),
    '@': multiConfig.process.alias,
    ...multiConfig.moduleAlias
}

第四步:修改 build/webpack.dev.conf.js 與 build/webpack.prod.conf.js 文件

  1. 引入新配置const multiConfig = require('../config/multi.conf')
  2. 可根據(jù) 項目本身需要 進行相應修改plugins
new webpack.DefinePlugin({
    'process.env.PROJ_NAME': '\"' + process.env.PROJ_NAME + '\"',
    'process.env.BASE_URL': '\"' + process.env.BASE_URL + '\"',
    'process.env.ASSETS_PUBLICPATH': '\"' + process.env.ASSETS_PUBLICPATH + '\"',
    'process.env.ASSETS_SUBDIRECTORY': '\"' + process.env.ASSETS_SUBDIRECTORY + '\"',
    'process.env.FILE_BASE_URL': '\"' + process.env.FILE_BASE_URL + '\"',
    'process.env.SOCKET_URL': '\"' + process.env.SOCKET_URL + '\"'
})

build/webpack.dev.conf.js 文件 修改如下:

  1. 引入文件
const chalk = require('chalk')
const pack = require('../package.json')
const os = require('os')
  1. 新增此方法 放在 頂部
function getIPAdress () {
    var interfaces = os.networkInterfaces()
    for (var devName in interfaces) {
        var iface = interfaces[devName]
        for (var i = 0; i < iface.length; i++) {
            var alias = iface[i]
            if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
                return alias.address
            }
        }    
    }
}

let host = ['localhost', '127.0.0.1', '0.0.0.0'].includes(devWebpackConfig.devServer.host) ? 'localhost' : devWebpackConfig.devServer.host
  1. 修改compilationSuccessInfo
//舊配置
// compilationSuccessInfo: {
//    messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
// },
//新配置
compilationSuccessInfo: {
    messages: [
            chalk`{bold.rgb(255,255,0) [${pack.name} => ${multiConfig.process.name}]} App running at:\n - Local: {bold.cyan http://${host}:${port}${config.dev.assetsPublicPath}}\n - Network: {bold.cyan http://${getIPAdress()}:${port}${config.dev.assetsPublicPath}}`
    ]
}

build/webpack.prod.conf.js 文件 修改如下:

  1. 引入 fs 文件 const fs = require('fs')
  2. 在頭部新增此方法
function isDirectory (path) {
    try {
        let stat = fs.statSync(path)
        return stat.isDirectory()
    } catch (e) {
    return false
    }
}
  1. 修改CopyWebpackPlugin
// copy custom static assets 舊配置
// new CopyWebpackPlugin([
//   {
//     from: path.resolve(__dirname, '../static'),
//     to: config.build.assetsSubDirectory,
//     ignore: ['.*']
//   }
// ])

// copy custom static assets 新配置
new CopyWebpackPlugin(multiConfig.process.publics.filter(name => isDirectory(path.resolve(__dirname, `../static/${name}`))).map(name => {
    return {
        from: path.resolve(__dirname, `../static/${name}`),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']
    }
})),

第五步:修改 build/index.js 文件

  1. 引入新配置
const multiConfig = require('../config/multi.conf')
  1. 放入全局對象
process.env.PROJ_NAME =  multiConfig.process.name;
process.env.BASE_URL =  multiConfig.process.baseUrl;
process.env.FILE_BASE_URL = multiConfig.process.fileBaseUrl;
process.env.SOCKET_URL = multiConfig.process.socketUrl;
process.env.ASSETS_SUBDIRECTORY=  multiConfig.process.assetsSubDirectory;
process.env.ASSETS_PUBLICPATH =  multiConfig.process.assetsPublicPath;
process.env.ASSETS_PUBLICS =  multiConfig.process.publics;

(3). 修改dev配置

assetsSubDirectory: multiConfig.process.assetsSubDirectory
assetsPublicPath: multiConfig.process.assetsPublicPath
proxyTable: multiConfig.process.proxyTable
host: multiConfig.process.host
port: multiConfig.process.port

(4).修改build配置

assetsSubDirectory: multiConfig.process.assetsSubDirectory
assetsPublicPath: multiConfig.process.assetsPublicPath

第六步: 配置package.json文件

 "scripts": {
    "dev:proj1": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "dev:proj2": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "dev:proj3": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "build": "npm install && npm run build:proj1 && npm run build:proj2 && npm run build:proj3 ",
    "build:proj1": "node build/build.js name=proj1",
    "build:proj2": "node build/build.js name=proj2",
    "build:proj3": "node build/build.js name=proj3"
}

第七步:啟動 / 打包 項目

npm run dev:proj1
npm run dev:proj2
npm run dev:proj3

npm run build :proj1 
npm run build :proj2 
npm run build :proj3

根據(jù)不同的命令啟動 或 打包 對應 的 模塊項目已經(jīng)完成啦 ~~~

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市膏蚓,隨后出現(xiàn)的幾起案子瓢谢,更是在濱河造成了極大的恐慌,老刑警劉巖驮瞧,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件氓扛,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機采郎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門千所,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蒜埋,你說我怎么就攤上這事淫痰。” “怎么了整份?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵待错,是天一觀的道長。 經(jīng)常有香客問我烈评,道長火俄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任讲冠,我火速辦了婚禮瓜客,結果婚禮上,老公的妹妹穿的比我還像新娘沟启。我一直安慰自己忆家,他們只是感情好,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布德迹。 她就那樣靜靜地躺著芽卿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪胳搞。 梳的紋絲不亂的頭發(fā)上卸例,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音肌毅,去河邊找鬼筷转。 笑死,一個胖子當著我的面吹牛悬而,可吹牛的內容都是我干的呜舒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼笨奠,長吁一口氣:“原來是場噩夢啊……” “哼袭蝗!你這毒婦竟也來了?” 一聲冷哼從身側響起般婆,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤到腥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蔚袍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乡范,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了晋辆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渠脉。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖瓶佳,靈堂內的尸體忽然破棺而出连舍,到底是詐尸還是另有隱情,我是刑警寧澤涩哟,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布索赏,位于F島的核電站,受9級特大地震影響贴彼,放射性物質發(fā)生泄漏潜腻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一器仗、第九天 我趴在偏房一處隱蔽的房頂上張望融涣。 院中可真熱鬧,春花似錦精钮、人聲如沸威鹿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忽你。三九已至,卻和暖如春臂容,著一層夾襖步出監(jiān)牢的瞬間科雳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工脓杉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留糟秘,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓球散,卻偏偏與公主長得像尿赚,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蕉堰,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內容