Vue打包部署(Koa)


打包之前的路由模式

目標配置打包之前的路由模式

在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/a www.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] // 改成只有靜態路由
})

此時,我們會發現地址已經變成我們想要的樣子了

image

提交代碼

性能分析和CDN的應用

目標: 對開發的應用進行性能分析和CDN的應用

性能分析

我們集成了 功能,寫了很多組件,最終都會打包成一堆文件,那么真實運行的性能如何呢?

我們可以使用vue-cli本身提供的性能分析工具,對我們開發的所有功能進行打包分析

它的應用非常簡單

$ npm run preview -- --report

這個命令會從我們的入口main.js進行依賴分析,分析出最大的包,方便我們進行觀察和優化

執行完這個命令,我們會看到如下的頁面

image

如圖所以,方塊越大,說明該文件占用的文件越大,文件越大,對於網絡帶寬和訪問速度的要求就越高,這也就是我們優化的方向

像這種情況,我們怎么優化一下呢

webpack排除打包

CDN是一個比較好的方式

文件不是大嗎?我們就不要把這些大的文件和那些小的文件打包到一起了,像這種xlsx,element這種功能性很全的插件,我們可以放到CDN服務器上,一來,減輕整體包的大小,二來CDN的加速服務可以加快我們對於插件的訪問速度

使用方式

先找到 vue.config.js, 添加 externalswebpack 不打包 xlsxelement

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頁面訪問問題

但是,此時存在兩個問題,

  1. 當我們刷新頁面,發現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('人資項目啟動')
})

解決生產環境跨域問題

  1. 當點擊登錄時,發現接口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文件
解決辦法:

    1. 去掉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文件目錄
  }
    1. 刪除vue-router的依賴,包括依賴包和package.json中的vue-router。使用了externals來外部引入vue-router的話則用這種方法。json

That is All !

感謝 ! ! !

線上地址:✈️


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM