使用vue-cli 3.x構建新專案
之前使用vue-cli2.0構建的多頁專案,對腳手架擴充套件了一些功能,但是存在一些問題,趁現在升級了vue-cli 3.x順便把專案重構一下
擴充套件點
改造 vue 專案為多頁(多模組)、多應用,和單頁(單模組)共存的專案
改造npm run dev命令,支援單模組啟動除錯服務 和 全量專案啟動除錯服務
改造npm run build命令,改為構建指定應用並打包部署到不同的服務環境
複製程式碼
為什麼擴充套件?
vue-cli 2.0版本官方不支援多頁,且2.0使用的webpack構建任務不支援多執行緒以及DLL,全靠自己擴充套件,不便於維護。vue-cli 2.0在多頁數量較多的情況下,不管本地熱更新還是構建打包,都是非常慢的。 現在的工程大多存在多個子應用,且多個子應用通常使用一套元件,一套公共方法,但是子應用採用單獨發包迭代。所以支援多應用是非常有必要的
新建vue-cli 3.0專案
這個網上很多教程,這裡就說了,這篇檔案講的很詳細
[使用 vue-cli 3 快速建立 Vue 專案](https://segmentfault.com/a/1190000014627083)
複製程式碼
vue-cli 3.0官方支援多頁,重點在於vue.config.js檔案的配置
const path = require('path');
// 新建一個multipage.js檔案,用來處理vue載入模板的入口;
const pages = require('./config/multipage').getPages();
module.exports = {
// 官方要求修改路徑在這裡做更改,預設是根目錄下,可以自行配置
baseUrl: './',
lintOnSave: false,
productionSourceMap: false,
// 在多核機器下會預設開啟。
parallel: require('os').cpus().length > 1,
pages,
css: { // css相關配置
extract: true, // 是否使用css分離外掛 ExtractTextPlugin
sourceMap: false, // 開啟 CSS source maps?
loaderOptions: {
less: {
javascriptEnabled: true
}
}, // css預設器配置項
modules: false // 啟用 CSS modules for all css / pre-processor files.
},
chainWebpack: config => {
if (process.env.NODE_ENV === 'production') {
config.module.rule('images').use('url-loader').loader('url-loader').tap(options => {
options.name = 'static/img/[name].[hash:8].[ext]';
return options;
});
config.plugin('extract-css').tap(() => [
{
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].css'
}
]);
}
},
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
config.output.path = path.join(__dirname, './dist')
config.output.filename = 'static/js/[name].[contenthash:8].js'
config.output.chunkFilename = 'static/js/[name].[contenthash:8].js'
}
Object.assign(config, {
// 打包時webpack不打包進去
externals: [
{'vue': 'window.Vue'},
{'vue-router': 'window.VueRouter'}
],
// 開發生產共同配置
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'assets': path.resolve(__dirname, './src/assets'),
'common': path.resolve(__dirname, './src/common'),
'components': path.resolve(__dirname, './src/components'),
'pages': path.resolve(__dirname, './src/pages'),
'vue$': 'vue/dist/vue.esm.js'
}
}
});
}
};
複製程式碼
說下配置檔案踩的坑
if (process.env.NODE_ENV === 'production') {
config.output.path = path.join(__dirname, './dist')
config.output.filename = 'static/js/[name].[contenthash:8].js'
// 這裡是不支援直接修改publicPath路徑的,必須用官方推薦的 baseUrl。
// config.output.publicPath = './'
config.output.chunkFilename = 'static/js/[name].[contenthash:8].js'
}
複製程式碼
最後打包出來的目錄格式是這樣的
multipage.js檔案
const path = require('path');
const fs = require('fs');
const URL = process.env.url; // 預設只載入一個檔案 singlepage || multipage
const NODE_ENV = process.env.NODE_ENV; // process環境變數
if (NODE_ENV === 'production' && URL === undefined) throw new Error('當前打包命令缺少url引數!')
const config = {
entry: 'index.js',
html: 'index.html',
pagesRoot: path.resolve(__dirname, '../src/pages')
};
const getRoutes = () => {
const allRoutes = [];
const findAllRoutes = (source, routes) => {
const globFiles = fs.readdirSync(source);
// 有URL 就預設載入那個指定的專案, 沒有就載入全部的 [ *.js ];
const files = URL ? [globFiles.find(item => item.includes(URL))] : globFiles;
files.forEach(filename => {
const fullname = path.join(source, filename);
const stats = fs.statSync(fullname);
if (!stats.isDirectory()) return;
// 檢測給定的路徑是否存在。
if (fs.existsSync(`${fullname}/${config.html}`)) {
routes.push(fullname);
} else {
findAllRoutes(fullname, routes);
}
});
};
findAllRoutes(config.pagesRoot, allRoutes);
return allRoutes;
};
const getPages = () => {
const pages = {};
getRoutes().forEach(route => {
let filename = route.slice(config.pagesRoot.length + 1);
pages[filename] = {
entry: `${route}/${config.entry}`,
template: `${route}/${config.html}`,
// 相容dev開發模式時 serve 全量專案和單個專案
filename: URL ? config.html : `${filename}/${config.html}`
};
});
// console.log(pages);
return pages;
};
module.exports = {
getRoutes,
getPages
}
複製程式碼
src 目錄下
啟動專案 dev
1. npm run dev (啟動全部專案) 包含多頁專案 和 單頁專案
2. 建議啟動單個專案,編譯時間短,啟動快 ( url=專案名 npm run dev )
複製程式碼
打包專案並一鍵部署到測試環境
url=專案名 npm run testbuild
這裡打包後是使用node.js實現的自動上傳;config檔案下的upload.js檔案我之前介紹過可以看我上一篇文章。
複製程式碼
"scripts": {
"dev": "vue-cli-service serve --open",
"lint": "vue-cli-service lint",
"testbuild": "vue-cli-service build && cross-env NODE_CONFIG=test node config/upload"
},
複製程式碼
cli3.x以後尤大進行了更深的封裝, 啟動或者打包都是依靠這個vue-cli-service去執行的;
// 原始碼部分位置 node_modules\@vue\cli-service\bin\vue-cli-service.js
#!/usr/bin/env node
const semver = require('semver')
const { error } = require('@vue/cli-shared-utils')
const requiredVersion = require('../package.json').engines.node
if (!semver.satisfies(process.version, requiredVersion)) {
error(
`You are using Node ${process.version}, but vue-cli-service ` +
`requires Node ${requiredVersion}.\nPlease upgrade your Node version.`
)
process.exit(1)
}
const Service = require('../lib/Service')
const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
// 主要核心功能在這裡;
const rawArgv = process.argv.slice(2)
const args = require('minimist')(rawArgv)
const command = args._[0]
// 這裡根據command的結果去執行是 run server 還是run build ;
service.run(command, args, rawArgv).catch(err => {
error(err)
process.exit(1)
})
複製程式碼
使用感受
修改後整體使用下來,無論是本地開發編譯,還是打包專案,提升都很明顯,感覺至少提升80%;
原因:cli3.x 升級了webpack4, 配置了多執行緒提升了速度,使用了快取,有些公共檔案不會被再次打包編譯;
複製程式碼
歡迎加我qq一起探討學習3544757498;
下一篇介紹本專案的技術選型和專案優化;