打包之前的路由模式
目標
配置打包之前的路由模式
在SPA單頁應用中,有兩種路由模式
hash模式 : #后面是路由路徑,特點是前端訪問,#后面的變化不會經過服務器
history模式:正常的/訪問模式,特點是后端訪問,任意地址的變化都會訪問服務器
開發到現在,一直都在用hash模式,打包我們嘗試用history模式
改成history模式非常簡單,只需要將路由的mode類型改成history即可
const createRouter = () => new Router({
mode: 'history', // require service support
scrollBehavior: () => ({ y: 0 }), // 管理滾動行為 如果出現滾動 切換就讓 讓頁面回到頂部
routes: [...constantRoutes] // 改成只有靜態路由
})
假設我們的地址是這樣的
www.xxxx/com/hr
/awww.xxxx/com/hr
/b
我們會發現,其實域名是www.xxxx/com
,hr是特定的前綴地址,此時我們可以配置一個base屬性,配置為hr
const createRouter = () => new Router({
mode: 'history', // require service support
base: '/hr/', // 配置項目的基礎地址
scrollBehavior: () => ({ y: 0 }), // 管理滾動行為 如果出現滾動 切換就讓 讓頁面回到頂部
routes: [...constantRoutes] // 改成只有靜態路由
})
此時,我們會發現地址已經變成我們想要的樣子了
提交代碼
性能分析和CDN的應用
目標
: 對開發的應用進行性能分析和CDN的應用
性能分析
我們集成了 功能,寫了很多組件,最終都會打包成一堆文件,那么真實運行的性能如何呢?
我們可以使用vue-cli本身提供的性能分析工具,對我們開發的所有功能進行打包分析
它的應用非常簡單
$ npm run preview -- --report
這個命令會從我們的入口main.js
進行依賴分析,分析出最大的包,方便我們進行觀察和優化
執行完這個命令,我們會看到如下的頁面
如圖所以,方塊越大,說明該文件占用的文件越大,文件越大,對於網絡帶寬和訪問速度的要求就越高,這也就是我們優化的方向
像這種情況,我們怎么優化一下呢
webpack排除打包
CDN是一個比較好的方式
文件不是大嗎?我們就不要把這些大的文件和那些小的文件打包到一起了,像這種xlsx,element這種功能性很全的插件,我們可以放到CDN服務器上,一來,減輕整體包的大小,二來CDN的加速服務可以加快我們對於插件的訪問速度
使用方式
先找到 vue.config.js
, 添加 externals
讓 webpack
不打包 xlsx
和 element
vue.config.js
// 排除 elementUI xlsx 和 vue
externals:
{
'vue': 'Vue',
'element-ui': 'ELEMENT',
'xlsx': 'XLSX'
}
再次運行,我們會發現包的大小已經大幅減小
CDN文件配置
但是,沒有被打包的幾個模塊怎么處理?
可以采用CDN的方式,在頁面模板中預先引入
vue.config.js
const cdn = {
css: [
// element-ui css
'https://unpkg.com/element-ui/lib/theme-chalk/index.css' // 樣式表
],
js: [
// vue must at first!
'https://unpkg.com/vue/dist/vue.js', // vuejs
// element-ui js
'https://unpkg.com/element-ui/lib/index.js', // elementUI
'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/jszip.min.js',
'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/xlsx.full.min.js'
]
}
但是請注意,這時的配置實際上是對開發環境和生產環境都生效的,在開發環境時,沒有必要使用CDN,此時我們可以使用環境變量來進行區分
let cdn = { css: [], js: [] }
// 通過環境變量 來區分是否使用cdn
const isProd = process.env.NODE_ENV === 'production' // 判斷是否是生產環境
let externals = {}
if (isProd) {
// 如果是生產環境 就排除打包 否則不排除
externals = {
// key(包名) / value(這個值 是 需要在CDN中獲取js, 相當於 獲取的js中 的該包的全局的對象的名字)
'vue': 'Vue', // 后面的名字不能隨便起 應該是 js中的全局對象名
'element-ui': 'ELEMENT', // 都是js中全局定義的
'xlsx': 'XLSX' // 都是js中全局定義的
}
cdn = {
css: [
'https://unpkg.com/element-ui/lib/theme-chalk/index.css' // 提前引入elementUI樣式
], // 放置css文件目錄
js: [
'https://unpkg.com/vue/dist/vue.js', // vuejs
'https://unpkg.com/element-ui/lib/index.js', // element
'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/xlsx.full.min.js', // xlsx 相關
'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/jszip.min.js' // xlsx 相關
] // 放置js文件目錄
}
}
注入CDN文件到模板
之后通過 html-webpack-plugin
注入到 index.html
之中:
config.plugin('html').tap(args => {
args[0].cdn = cdn
return args
})
找到 public/index.html
。通過你配置的CDN Config
依次注入 css 和 js。
<head>
<!-- 引入樣式 -->
<% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
<link rel="stylesheet" href="<%=css%>">
<% } %>
</head>
<!-- 引入JS -->
<% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%=js%>"></script>
<% } %>
最后,進行打包
$ npm run build:prod
在nodejs環境中應用並代理跨域
目標
將打包好的代碼打包上線,並在nodejs中代理跨域. (打包命令用 zip -r dist.zip ./dist)
使用koa框架部署項目
到現在為止,我們已經完成了一個前端工程師的開發流程,按照常規的做法,此時,運維會將我們的代碼部署到阿里雲的ngix服務上,對於我們而言,我們可以將其部署到本機的nodejs環境中
部署 自動化部署 /手動部署
第一步,建立web服務文件夾 hrServer
$ mkdir hrServer #建立hrServer文件夾
第二步,在該文件夾下,初始化npm
$ npm init -y
第三步,安裝服務端框架koa(也可以采用express或者egg)
$ npm i koa koa-static
第四步,拷貝上小節打包的dist目錄到hrServer/public
下(打包命令用 zip -r dist.zip ./dist)
[root@VM-12-13-centos public]# pwd
/root/vue/hrServer/public
[root@VM-12-13-centos public]# ls
favicon1.ico favicon.ico index.html static
第五步,在根目錄下創建app.js,代碼如下
const Koa = require('koa')
const serve = require('koa-static');
const app = new Koa();
app.use(serve(__dirname + "/public")); //將public下的代碼靜態化
app.listen(3333, () => {
console.log('人資項目啟動')
})
第六步,啟動項目
node app.js
此時,我們可以訪問,http://ip:3333
頁面出來了
解決history頁面訪問問題
但是,此時存在兩個問題,
- 當我們刷新頁面,發現404
這是因為我們采用了history的模式,地址的變化會引起服務器的刷新,我們只需要在app.js對所有的地址進行一下處理即可(測試發現還是存在問題)
安裝 koa中間件
$ npm i koa2-connect-history-api-fallback # 專門處理history模式的中間件
注冊中間件
const Koa = require('koa')
const serve = require('koa-static');
const { historyApiFallback } = require('koa2-connect-history-api-fallback');
const path = require('path')
const app = new Koa();
// 這句話 的意思是除接口之外所有的請求都發送給了 index.html
app.use(historyApiFallback({
whiteList: ['/prod-api']
})); // 這里的whiteList是 白名單的意思
app.use(serve(__dirname + "/public")); //將public下的代碼靜態化
app.listen(3333, () => {
console.log('人資項目啟動')
})
解決生產環境跨域問題
- 當點擊登錄時,發現接口404
前面我們講過,vue-cli的代理只存在於開發期,當我們上線到node環境或者ngix環境時,需要我們再次在環境中代理
在nodejs中代理
安裝跨域代理中間件
$ npm i koa2-proxy-middleware
配置跨越代理
const Koa = require('koa')
const serve = require('koa-static');
const { historyApiFallback } = require('koa2-connect-history-api-fallback')
const path = require('path')
const proxy = require('koa2-proxy-middleware')
const app = new Koa();
app.use(proxy({
targets: {
// (.*) means anything
'/prod-api/(.*)': {
target: 'http://ihrm-java.itheima.net/api', //后端服務器地址
changeOrigin: true,
pathRewrite: {
'/prod-api': ""
}
}
}
}))
app.use(historyApiFallback({
whiteList: ['/prod-api']
})) // 這里的whiteList是 白名單的意思
app.use(serve(__dirname + "/public")); //將public下的代碼靜態化
app.listen(3333, () => {
console.log('人資項目啟動')
})
注意:這里之所以用了pathRewrite,是因為生產環境的請求基礎地址是 /prod-api,需要將該地址去掉
此時,我們的項目就可以跨域訪問了!
雲服務持續運行
npm install forever -g // 安裝 forever
forever start app.js
打包部署過程出現問題
1、訪問部署地址時,控制台報 :Vue is not defined
解決辦法:
修改 cdn 配置如下:
cdn = {
css: [
'https://unpkg.com/element-ui/lib/theme-chalk/index.css' // 提前引入elementUI樣式
], // 放置css文件目錄
js: [
// vue
'https://cdn.staticfile.org/vue/2.5.22/vue.min.js',
'https://cdn.staticfile.org/vue-router/3.0.2/vue-router.min.js',
'https://cdn.staticfile.org/vuex/3.1.0/vuex.min.js',
'https://cdn.staticfile.org/axios/0.19.0-beta.1/axios.min.js',
'https://cdn.bootcss.com/element-ui/2.13.0/index.js',
'https://cdn.bootcss.com/echarts/4.6.0/echarts-en.common.js',
// 'https://unpkg.com/vue/dist/vue.js', // vuejs
// 'https://unpkg.com/element-ui/lib/index.js', // element
'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/xlsx.full.min.js', // xlsx 相關
'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/jszip.min.js' // xlsx 相關
] // 放置js文件目錄
}
修改public/index.html文件的css、js引入
<!-- 打包上線:開始 -->
<!-- 引入樣式 -->
<% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%=css%>" rel="preload" as="style" >
<link rel="stylesheet" href="<%=css%>" as="style" >
<% } %>
<!-- 引入JS -->
<% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
<link href="<%=js%>" rel="preload" as="script" >
<script src="<%=js%>"></script>
<% } %>
<!-- 打包上線:結束 -->
2、做完上面兩個步驟后,重新打包部署,訪問報 Cannot redefine property: $router
原因:由於在項目中安裝了vue-router的依賴而且用Vue.use()使用了vue-router,還在index.html頁面引入了vue-router.js文件
解決辦法:
-
- 去掉index.html中的vue-router.js文件的引入。若是沒有使用externals的話能夠直接使用這種方法。(本次在 cdn 中將 vue-router.js 注釋重新打包部署解決問題)
cdn = {
css: [
'https://unpkg.com/element-ui/lib/theme-chalk/index.css' // 提前引入elementUI樣式
], // 放置css文件目錄
js: [
// vue
'https://cdn.staticfile.org/vue/2.5.22/vue.min.js',
// 'https://cdn.staticfile.org/vue-router/3.0.2/vue-router.min.js',
'https://cdn.staticfile.org/vuex/3.1.0/vuex.min.js',
'https://cdn.staticfile.org/axios/0.19.0-beta.1/axios.min.js',
'https://cdn.bootcss.com/element-ui/2.13.0/index.js',
'https://cdn.bootcss.com/echarts/4.6.0/echarts-en.common.js',
// 'https://unpkg.com/vue/dist/vue.js', // vuejs
// 'https://unpkg.com/element-ui/lib/index.js', // element
'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/xlsx.full.min.js', // xlsx 相關
'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/jszip.min.js' // xlsx 相關
] // 放置js文件目錄
}
-
- 刪除vue-router的依賴,包括依賴包和package.json中的vue-router。使用了externals來外部引入vue-router的話則用這種方法。json
That is All !
感謝 ! ! !
線上地址:✈️