vue-cli3單頁構(gòu)建大型項目方案
一、vue-cli3單頁面構(gòu)建方案
1、在目標文件夾內(nèi)執(zhí)行
vue ui ; 一個ui版界面,用于創(chuàng)建vue項目;
2、打開router文件夾內(nèi)的index,看情況配置router的模式,是默認的hash還是history?ps:個人推介history模式,因為內(nèi)嵌如app的H5頁面的話,有可能某些app是不允許頁面上帶有'#'的,而hash會在url上利用#來做路由轉(zhuǎn)發(fā)。ps:history模式在發(fā)布到服務(wù)器上需要nginx配置一下。詳情請自行百度。
const router = new VueRouter({
base: '/',
mode: 'history', //還可設(shè)置為'hash'模式
routes
})
3、在根目錄新建vue.config.js,覆蓋webpack配置,將如下內(nèi)容copy到文件中,作為初始配置
// const webpack = require('webpack')
module.exports = {
lintOnSave: false, // 禁止eslint
devServer: {
open: true, // 構(gòu)建完成自動打開瀏覽器
},
configureWebpack: {
plugins: [
// 全局配置node_modules中的模塊,使用時無需引入
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"windows.jQuery": "jquery"
})
]
},
// webpack 鏈接 API,用于生成和修改 webapck 配置
chainWebpack: (config) => {
// 取消 chunks,每個頁面只對應(yīng)一個單獨的 JS / CSS
config.optimization.splitChunks({
cacheGroups: {}
});
// config
// .plugin('webpack-bundle-analyzer')
// .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
},
pluginOptions: {
}
}
4、配置完這些后,npm run serve啟動項目,會加載如下兩個js
npm run serve

app.js:是所有單頁面首次渲染都必須加載的js,內(nèi)部合并了框架及js(如vue、vue-x、vue-router及非異步組件但引用了的node_modules中的模塊),及所有頁面公用的模塊。about.js:是每個頁面獨立的js,這個跟router中引用模塊的方式有關(guān)。
具體詳解如下:
1、
import Home from '../views/Home.vue'
這種引用方式引用頁面模版組件,就不會出現(xiàn)about.js文件,因為屬于同步模塊,當前件建的js會被打包進app.js。但是此種隨著頁面的增多,公用的app.js會越來越大??辞闆r在app.js大小接受的前提下權(quán)衡使用;2、
const routes = [
{
path: '/',
name: 'Home',
// component: Home
component: () => import(/* webpackChunkName: "home" */ '../views/Home.vue') // webpack的魔法注釋,將拆分出的js命名為home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
這種引用方式就是異步引用模版組件,不會將當前組建的js打包進app.js,就不會出現(xiàn)1種的問題。因為只要沒有加載到對應(yīng)頁面,就不會加載對應(yīng)頁面的js。對應(yīng)頁面的js會最為獨立的js單獨的動態(tài)引入,如同上圖的about.js,在進入about頁面時才會引入。
3、如果在main.js中引入的node_modules包,則會直接打包進app.js,這個逃不掉。
ps:最終結(jié)論,建議每個頁面都異步引用頁面模版。
5、每個頁面如果引了node_mudules就會存在相對應(yīng)的vendors-home.js,如果沒引入node_mudules的話,每個頁面按需組件就不會存在vendors-home.js這個文件,如下圖:


6、區(qū)分本地、測試、線上環(huán)境
ps:官網(wǎng)提供一種方案,但是需要建立多個環(huán)境配置的配置文件,嫌麻煩,就不使用官方的方式,使用如下插件拆分環(huán)境:
cross-env:https://github.com/kentcdodds/cross-env
cnpm i cress-env --save-dev // 更改node環(huán)境變量插件
之后在package.json中加入如下三行配置,即可區(qū)分本地、測試、線上環(huán)境
"scripts": {
"serve": "cross-env NODE_ENV=development vue-cli-service serve",
"test": "cross-env NODE_ENV=test vue-cli-service build",
"build": "cross-env NODE_ENV=production vue-cli-service build"
},
在vue.config.js中執(zhí)行如下代碼即可打印出當前環(huán)境。
console.log(process.env.NODE_ENV)
在src目錄下新建config目錄,進入目錄,新建gateway.config.js文件用于配置不同環(huán)境接口host,代碼如下:gateway.config.js文件內(nèi)容如下:
// 開發(fā)環(huán)境地址(npm run serve)
const devHost = {
// 接口地址域名相關(guān)
baseApi: 'https://abc.com',
}
// 測試環(huán)境地址(npm run test)
const testHost = {
// 接口地址域名相關(guān)
baseApi: 'https://abc.com',
}
// 線上環(huán)境地址(npm run build)
const proHost = {
// 接口地址域名相關(guān)
baseApi: 'https://abc1.com',
}
// 區(qū)分環(huán)境選擇靜態(tài)資源地址
const env = process.env.NODE_ENV
let exportConfig = ''
if (env === 'production') {
exportConfig = proHost
} else if (env === 'test') {
exportConfig = testHost
} else {
exportConfig = devHost
}
export default exportConfig
結(jié)束:之后只需要在接口api的js文件中引入此文件即可。發(fā)布時區(qū)分環(huán)境打包。
7、淺談項目引入第三方插件方案
ps:原則:移動端單個js大小不超過200k;pc端單個js不超過400k;
1.vue模塊化引入node_modules包插件:
前提,各個頁面都是異步加載,這樣的好處是單個頁面的js不會被打包進公共app.js中。之后在單個js中引入第三方庫。但是據(jù)測試:這種模塊化引入第三方插件,比cdn模式引入的js體積至少要大2唄,因為webpack內(nèi)部對每個第三方庫進行了二次處理,會增大js體積。權(quán)衡js大小使用。
2.cdn模式引入第三方插件:
提供這種方式,是因為有些庫是不支持vue的,只支持cdn模式引入,而且比較輕量級,可以選擇這種方案,異步cdn模式引入第三方插件,這些方式最下方腳手架示例中都有demo;
8、項目中常用的打包插件及第三方庫
1.vue https://cn.vuejs.org
2.vue-router https://router.vuejs.org
3.vue-x https://vuex.vuejs.org
4.sass https://www.sass.hk
5.axios http://www.axios-js.com/
6.normalize.css http://necolas.github.io/normalize.css/
7.n-zepto https://npm.taobao.org/package/n-zepto
8.webpack-bundle-analyzer https://github.com/webpack-contrib/webpack-bundle-analyzer
下方是vue-cli3內(nèi)置插件(直接在vue.config.js中配置):
如下插件可參考vue-cli3官網(wǎng)配置方法:
https://cli.vuejs.org/zh/config/#css-sourcemap
9.autoprefixer:自動添加瀏覽器前綴。(如:-webkit-等)
10.url-loader:改變靜態(tài)資源引用路徑
11.ProvidePlugin:全局配置node_modules中的模塊
具體配置方法如下(比較全的vue.config.js配置):
const webpack = require('webpack')
const processEnv = process.env.VUE_APP_ENV; // 區(qū)分環(huán)境(值:production、development、test)
const isPro = processEnv === 'production'; // 判斷production環(huán)境
const outputDir = 'dist'; // 輸出文件目錄(默認dist)
const assetsDir = ''; // 配置放置生成的靜態(tài)資源 (js、css、img、fonts) 的 (相對于 outputDir 的) 目錄
// 區(qū)分環(huán)境選擇cdn地址
let publicPath = '' // 靜態(tài)資源引用路徑
let fontPublicPath = '' // 字體圖標引用的cdn路徑
let imgPublicPath = '' // css引用圖片的cdn路徑(c2c/static/img)
if (processEnv === 'production') {
publicPath = 'https://abc.com/c2c/shop' // 正式環(huán)境靜態(tài)資源css、js等cdn路徑
fontPublicPath = `https://abc.com/c2c/shop/${assetsDir ? assetsDir + '/' : '/'}fonts` // 正式環(huán)境字體圖標引用的cdn路徑
imgPublicPath = `https://abc.com/c2c/shop/${assetsDir ? assetsDir + '/' : '/'}/img` // 正式環(huán)境css引用圖片的cdn路徑
} else if (processEnv === 'test') {
// publicPath = './' // 正式環(huán)境靜態(tài)資源css、js等cdn路徑
publicPath = 'https://bcd.com/c2c/shop/dist' // 測試環(huán)境靜態(tài)資源css、js等cdn路徑
fontPublicPath = ''
imgPublicPath = ''
} else {
publicPath = '/'
fontPublicPath = ''
imgPublicPath = ''
}
const devServerHost = 'localhost';
const devServerPort = '8080'; // 端口號
const devServerOpen = true; // 熱啟動后自動打開瀏覽器
module.exports = {
// 配置生成dist里面static的cdn資源路徑(測試環(huán)境為./,正式環(huán)境走cdn路徑)
publicPath: publicPath,
// 輸出文件目錄(默認dist)
outputDir,
// 配置放置生成的靜態(tài)資源 (js、css、img、fonts) 的 (相對于 outputDir 的) 目錄
assetsDir,
devServer: {
host: devServerHost,
port: devServerPort,
open: devServerOpen, // 構(gòu)建完成自動打開瀏覽器
// eslint檢測影響代碼編譯,注釋調(diào)不會影響代碼編譯
// overlay: {
// warnings: true,
// errors: true
// }
},
lintOnSave: processEnv === 'development' ? true : false, // 開發(fā)環(huán)境開啟eslint,測試和線上編輯代碼禁止eslint
// webpack 配置,鍵值對象時會合并配置,為方法時會改寫配置
configureWebpack: config => {
// 擴展資源,不將部分資源js等打入包內(nèi)引用cdn資源
let externals = {
// 'swiper': 'Swiper',
};
config.externals = externals;
//警告 webpack 的性能提示
config.performance = {
hints: isPro ? 'warning' : false, // 本地開發(fā)不顯示警告
// 入口起點的最大體積
maxEntrypointSize: 512000, // 500kib
// 生成文件的最大體積
maxAssetSize: 307200, // 300kib
// 只給出 js 文件的性能提示
assetFilter(assetFilename) {
return assetFilename.endsWith('.js');
}
};
},
// webpack 鏈接 API,用于生成和修改 webapck 配置
chainWebpack: (config) => {
// 取消 chunks,每個頁面只對應(yīng)一個單獨的 JS / CSS
config.optimization.splitChunks({
cacheGroups: {}
});
// 全局配置node_modules中的模塊,使用時無需引入
config.plugin('provide').use(webpack.ProvidePlugin, [{
$: "n-zepto",
Zepto: "n-zepto",
"window.Zepto": "n-zepto"
}]);
config.module
.rule('images')
.use('url-loader')
.loader('url-loader')
.tap(options => Object.assign(options, {
limit: 10240, // 小于10k,壓縮圖片 => base64
// limit: 3000,
publicPath: imgPublicPath,
name: `[name].[hash:8].[ext]`
}))
// 設(shè)置fonts字體文件引用的路徑
config.module
.rule('fonts')
.test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i)
.use('url-loader')
.loader('file-loader')
.tap(options => Object.assign(options, {
limit: 5000,
publicPath: fontPublicPath,
name: '[name].[hash:8].[ext]'
}))
// npm run report;打印app.js的模塊報告,查看各個模塊;
if (processEnv === 'report') {
config
.plugin('webpack-bundle-analyzer')
.use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
}
},
// css配置處理
css: {
// 是否使用css分離插件 ExtractTextPlugin;true:頁面css獨立分割,false:頁面css同一打包;
extract: true,
// 開啟 CSS source maps(默認false)線上關(guān)閉,測試和本地開啟
sourceMap: isPro ? false : true,
// css預設(shè)器配置項
loaderOptions: {
sass: {
// sass的公共方法和變量,需要預編譯;
prependData: `
@import "@/assets/css/global.scss";
@import "@/assets/css/func.scss";
`
},
postcss: {
plugins: [
// 瀏覽器自動加前綴
require('autoprefixer')({
overrideBrowserslist: [
"Android 4.0",
"iOS 7",
"Chrome > 31",
"ff > 31",
"ie >= 8"
]
}),
]
}
},
// 啟用 CSS modules for all css / pre-processor files.
requireModuleExtension: false
},
// 構(gòu)建時開啟多進程處理 babel 編譯
parallel: require('os').cpus().length > 1,
pwa: {
iconPaths: {
favicon32: 'favicon.ico',
favicon16: 'favicon.ico',
appleTouchIcon: 'favicon.ico',
maskIcon: 'favicon.ico',
msTileImage: 'favicon.ico'
},
},
// 第三方插件配置
pluginOptions: {
// ...
}
}
9、一個基礎(chǔ)配置較為完善的基于vue-cli3的單頁面項目方案腳手架:
項目腳手架集合project-init
其中的cli-start-spa文件夾,內(nèi)部readme有項目細節(jié)。
到此這篇關(guān)于vue-cli3單頁構(gòu)建大型項目方案的文章就介紹到這了,更多相關(guān)vue-cli3單頁構(gòu)建 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
electron-vue+electron-updater實現(xiàn)自動更新(步驟源碼)
這篇文章主要介紹了electron-vue+electron-updater實現(xiàn)自動更新,步驟源碼包括autoUpdater.js操控更新js文件,main.js也就是package.json內(nèi)的main指向的js文件,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-10-10
使用vite搭建ssr活動頁架構(gòu)的實現(xiàn)
本文主要介紹了使用vite搭建ssr活動頁架構(gòu),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-07-07
vue點擊Dashboard不同內(nèi)容 跳轉(zhuǎn)到同一表格的實例
這篇文章主要介紹了vue點擊Dashboard不同內(nèi)容 跳轉(zhuǎn)到同一表格的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11

