vue项目部署篇 -线上部署优化

打包注意事项

打包完的项目 dist文件夹如果 已经启动服务,此时不能重新打包,(因为文件 在占用),需要停止服务,再进行重新打包。

vue打包上线移除 console

两种插件可选择

1、babel-plugin-transform-remove-console

比较流行的解决办法是使用 babel 的一个插件,因为webpack 打包时会使用 babel 进行代码降级,所以babel 插件可以在打包过程中,将 console 移除

安装

npm install babel-plugin-transform-remove-console --save-dev

配置

在项目根目录下的 babel.config 文件中加入如下代码

module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  // 配置插件的名称
  plugins:['transform-remove-console']
}

2. terser-webpack-plugin

安装

npm install terser-webpack-plugin --save-dev

注意: 项目根目录下新建 webpack.config.js,(不是vue.config.js)注册此插件

const TerserPlugin = require('terser-webpack-plugin')
module.exports = {
  optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()],
    terserOptions: {
      compress: {
        drop_console: true
      }
    }
  }
}

接下来就可以重新编译了。。

判断运行模式打包

使用 babel-plugin-transform-remove-console 插件会有一个问题(使用terser-webpack-plugin没有此问题),就是一旦安装并配置好后,无论运行

npm run build

还是运行

npm run serve

都会删除 console,语句,因为我们开发阶段都是使用 serve 命令启动的,所以导致开发阶段我们所有的console 语句都消失了

解决办法就是明确告诉此插件当前是开发环境还是生产环境

修改 babel.config.js 中的代码

const prodPlugins = []
if (process.env.NODE_ENV === 'production') {
  prodPlugins.push('transform-remove-console')
}

module.exports = {
presets: [
‘@vue/cli-plugin-babel/preset’
],
plugins: […prodPlugins]
}

此时,只有在生产环境下,才会去除 console

开发环境/部署环境打包

步骤

在 src 目录下新建 prod_env.js 和 dev_env.js,将main.js 中代码分别拷贝到这两个文件中,现在就可以删除 main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false

import ElementUI from ‘element-ui’;
import ‘element-ui/lib/theme-chalk/index.css’;
Vue.use(ElementUI);

// import request from “./network/request”
// Vue.prototype.$http = request

import axios from “axios”
axios.defaults.baseURL=‘http://127.0.0.1:8888/api/private/v1/’
// 请求拦截
axios.interceptors.request.use(config=>{
config.headers.Authorization=sessionStorage.getItem(‘token’)
// console.log(config);
return config
})
// 响应拦截
axios.interceptors.response.use(res=>{
return res.data
})
Vue.prototype.$http = axios

// 字体图标
import ‘./assets/font/iconfont.css’

// 时间格式化
// import moment from “moment”
// 全局的时间格式过滤器
Vue.filter(‘formatTime’, v => {
return moment.unix(v / 1000).format(‘YYYY-MM-DD HH:mm:SS’)
})

// 富文本
import VueQuillEditor from ‘vue-quill-editor’
// require styles
import ‘quill/dist/quill.core.css’
import ‘quill/dist/quill.snow.css’
import ‘quill/dist/quill.bubble.css’
// 使用CSN方式使用插件,use不能省略,还需要使用use使用改插件
Vue.use(VueQuillEditor)

new Vue({
router,
render: h => h(App)
}).$mount(’#app’)

配置打包时的入口文件

项目根目录下新建 vue.config.js

 module.exports={
 		// 链式操作
     chainWebpack:config=>{
         //  项目部署时的入口文件
        config.when(process.env.NODE_ENV === 'production',config=>{
            config.entry('app').clear().add('./src/prod_env.js')
        })
         // 配置开发时的入口文件
        config.when(process.env.NODE_ENV === 'development',config=>{
         // 使用开发阶段的配置
            config.entry('app').clear().add('./src/dev_env.js')
        })
    }
}

开发时,使用 npm run serve 命令,NODE_ENV 的值就是 developmnent ,所以会将 dev.env.js 作为入口文件
部署时,使用 npm run build 命令,NODE_ENV 的值就是 production,所以会将 prod_evn.js 作为入口文件

项目打包减少体积

解决方法主要是两个,一个是使用CDN,一个是路由的懒加载

项目运行 npm run build后使用vscode打开

//项目运行时依赖文件,伴随着在main.js中引入的插件增加,打包后的体积也会增加
chunk-vendors.b4c61135.js

默认情况下,凡是通过 import 方式引入的包,打包时都会被打包,这就会导致最后的包体积比较大,伴随而来的就是程序的加载速度慢

使用CDN

注意: index.html中不能同时使用CDN和本地引入(会报错,浏览器会首先使用script中引入的插件)

https://www.jsdelivr.com/ CDN网站

点击搜索,vuecdn,复制或 HTML的script标签

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f5l8M8Cr-1588228759900)(images/image-20200429200418462.png)]

修改生产环境入口文件

凡是通过CDN节点方式引用的包,在这里都注释掉,

注意: 使用CSN方式使用插件,use不能省略,还需要使用use使用改插件

// import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false

// import ElementUI from ‘element-ui’;
// import ‘element-ui/lib/theme-chalk/index.css’;
Vue.use(ElementUI);

// import request from “./network/request”
// Vue.prototype.$http = request

// import axios from “axios”
axios.defaults.baseURL=‘http://127.0.0.1:8888/api/private/v1/’
// 请求拦截
axios.interceptors.request.use(config=>{
config.headers.Authorization=sessionStorage.getItem(‘token’)
// console.log(config);
return config
})
// 响应拦截
axios.interceptors.response.use(res=>{
return res.data
})
Vue.prototype.$http = axios

// 字体图标
import ‘./assets/font/iconfont.css’

// 时间格式化
// import moment from “moment”
// 全局的时间格式过滤器
Vue.filter(‘formatTime’, v => {
return moment.unix(v / 1000).format(‘YYYY-MM-DD HH:mm:SS’)
})

// 富文本
// import VueQuillEditor from ‘vue-quill-editor’
// require styles
// import ‘quill/dist/quill.core.css’
// import ‘quill/dist/quill.snow.css’
// import ‘quill/dist/quill.bubble.css’
// 使用CSN方式使用插件,use不能省略,还需要使用use使用改插件
Vue.use(VueQuillEditor)

new Vue({
router,
render: h => h(App)
}).$mount(’#app’)

public/index.html 中引入CDN

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset=utf-8>
<meta http-equiv=X-UA-Compatible content=IE=edge>
<meta name=viewport content=width=device-width,initial-scale=1.0>
<link rel=icon href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel=stylesheet type=text/css href=https://cdn.jsdelivr.net/npm/quill@1.3.7/dist/quill.core.css />
<link rel=stylesheet type=text/css href=https://cdn.jsdelivr.net/npm/quill@1.3.7/dist/quill.snow.css />
<link rel=stylesheet type=text/css href=https://cdn.jsdelivr.net/npm/quill@1.3.7/dist/quill.bubble.css />
<link rel=stylesheet type=text/css
href=https://cdn.jsdelivr.net/npm/element-ui@2.13.1/lib/theme-chalk/index.css>

<script type=text/javascript src=https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js></script>
<script type=text/javascript src=https://cdn.jsdelivr.net/npm/quill@1.3.7/dist/quill.min.js></script>
<script type=text/javascript
src=https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.6/dist/vue-quill-editor.min.js>
</script>
<script src=https://unpkg.com/axios/dist/axios.min.js></script>
<!-- <script src=“https://unpkg.com/vue-router/dist/vue-router.js”></script> -->
<script src=https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js></script>
<script src=https://cdn.bootcss.com/echarts/4.7.0/echarts.js></script>
<script src=https://cdn.jsdelivr.net/npm/element-ui@2.13.1/lib/index.js></script>
<script src=https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js></script>
</head>

<body>
<noscript>
<strong>We’re sorry but <%= htmlWebpackPlugin.options.title %> doesn’t work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id=app></div>
<!-- built files will be auto injected -->
</body>

</html>

vue.config.js 中添加配置

https://cli.vuejs.org/zh/config/#vue-config-js 官方脚手架 vue.config.js配置

module.exports = {
  // 配置webpack的解析配置项
  configureWebpack: {
    resolve: {
      alias: {
        "assets": "@/assets",
        "components": "@/components",
        "network": "@/network",
        'common': '@/common'
      }
    }
  },
  chainWebpack: config => {
    /**
     * 配置打包时使用CDN节点,左面放package.json中的扩展的名称,右面放项目依赖的名称(项目初始化要用的名称)
     * externals外部扩展的意思,使用外部CDN节点进行打包
     * 3、名称带中横线的需使用引号包起来
     *  */
    config.set("externals", {
      vue: 'Vue',
      moment: 'moment',
      "element-ui": 'element-ui',
      axios: 'axios',
      "vue-quill-editor": "vue-quill-editor"
    })
  }
}

总结: webpack在打包时,是以public/index.html作为模板,CDN节点写到其中,打包后,也就会在打包后的项目中引入cdn节点。

开发/部署阶段自动判断

部署的时候 index.html 中使用这些 CDN 节点的依赖,开发阶段,不希望 index.html 中的这些引用存在,而是继续使用本地的包,这就需要在 index.html 中根据当前的打包环境是开发还是部署,动态的决定 index.html 中是否显示这些引用

步骤

使用 webpack中自带的插件 html插件进行配置,在 index.html 中增加判断,是否使用 CDN

htmlWebpackPlugin.options 使用的是vue.config中的config.plugin('html')的插件属性

index.html

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset=utf-8>
<meta http-equiv=X-UA-Compatible content=IE=edge>
<meta name=viewport content=width=device-width,initial-scale=1.0>
<link rel=icon href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<!-- 使用vue自带的lodash语法,在这里进行判断是否引入CDN -->
<!-- htmlWebpackPlugin.options 使用的是vue.config中的config.plugin(‘html’)的插件属性 -->
<% if( htmlWebpackPlugin.options.isProd) { %>
<link rel=stylesheet type=text/css href=https://cdn.jsdelivr.net/npm/quill@1.3.7/dist/quill.core.css />
<link rel=stylesheet type=text/css href=https://cdn.jsdelivr.net/npm/quill@1.3.7/dist/quill.snow.css />
<link rel=stylesheet type=text/css href=https://cdn.jsdelivr.net/npm/quill@1.3.7/dist/quill.bubble.css />
<link rel=stylesheet type=text/css
href=https://cdn.jsdelivr.net/npm/element-ui@2.13.1/lib/theme-chalk/index.css>

<script type=text/javascript src=https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js></script>
<script type=text/javascript src=https://cdn.jsdelivr.net/npm/quill@1.3.7/dist/quill.min.js></script>
<script type=text/javascript
src=https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.6/dist/vue-quill-editor.min.js>
</script>
<script src=https://unpkg.com/axios/dist/axios.min.js></script>
<!-- <script src=“https://unpkg.com/vue-router/dist/vue-router.js”></script> -->
<script src=https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js></script>
<script src=https://cdn.bootcss.com/echarts/4.7.0/echarts.js></script>
<script src=https://cdn.jsdelivr.net/npm/element-ui@2.13.1/lib/index.js></script>
<script src=https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js></script>
<% } %>

</head>

<body>
<noscript>
<strong>We’re sorry but <%= htmlWebpackPlugin.options.title %> doesn’t work properly without JavaScript enabled.
Please enable it to continue.</strong>
</noscript>
<div id=app></div>
<!-- built files will be auto injected -->
</body>

</html>

vue.congfig.js

当前配置的自动判断引入哪一个配置文件

module.exports = {
  // 配置webpack的解析配置项
  configureWebpack: {
    resolve: {
      alias: {
        "assets": "@/assets",
        "components": "@/components",
        "network": "@/network",
        'common': '@/common'
      }
    }
  },
  // 链式操作
  chainWebpack: config => {
    //  项目部署时的入口文件
    config.when(process.env.NODE_ENV === 'production', config => {
      // 使用部署阶段的配置
      config.entry('app').clear().add('./src/prod.env.js')
      /**
       * 配置,项目部署打包时使用CDN节点的别名方式进行打包,而不用import本地引入(原理是使用CDN模块中暴漏出来的对象,然后再这里配置在编译时webpack要使用的模块别名)
    * 1、配置打包时使用CDN节点,左面放package.json中的扩展的名称,右面放项目依赖的名称(项目初始化要用的名称)
    * 2、externals外部扩展的意思,使用外部CDN节点进行打包
    * 3、名称带中横线的需使用引号包起来
    *  */
      config.set("externals", {
        vue: 'Vue',
        moment: 'moment',
        "element-ui": 'element-ui',
        axios: 'axios',
        "vue-quill-editor": "VueQuillEditor"
      })
  <span class="token comment"><span class="hljs-comment">// 根据开发模式,自动判断是否使用index.html中的CDN</span></span>
  config<span class="token punctuation">.</span><span class="token function">plugin</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string">'html'</span></span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">tap</span><span class="token punctuation">(</span><span class="hljs-function"><span class="hljs-params">args</span> </span><span class="token operator"><span class="hljs-function">=&gt;</span></span> <span class="token punctuation">{</span>
    args<span class="token punctuation">[</span><span class="token number"><span class="hljs-number">0</span></span><span class="token punctuation">]</span><span class="token punctuation">.</span>title <span class="token operator">=</span> <span class="token string"><span class="hljs-string">"超级商城后台管理"</span></span>
    <span class="token comment"><span class="hljs-comment">// 是否是生产模式</span></span>
    args<span class="token punctuation">[</span><span class="token number"><span class="hljs-number">0</span></span><span class="token punctuation">]</span><span class="token punctuation">.</span>isProd <span class="token operator">=</span> <span class="token boolean"><span class="hljs-literal">true</span></span>
    <span class="token comment"><span class="hljs-comment">// 注意最后要把数组返回</span></span>
    <span class="token keyword"><span class="hljs-keyword">return</span></span> args
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment"><span class="hljs-comment">// 配置开发时的入口文件</span></span>
config<span class="token punctuation">.</span><span class="token function">when</span><span class="token punctuation">(</span>process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NODE_ENV</span> <span class="token operator">===</span> <span class="token string"><span class="hljs-string">'development'</span></span><span class="token punctuation">,</span> config <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment"><span class="hljs-comment">// 使用开发阶段的配置</span></span>
  config<span class="token punctuation">.</span><span class="token function">entry</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string">'app'</span></span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">clear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string">'./src/dev_env.js'</span></span><span class="token punctuation">)</span>

  <span class="token comment"><span class="hljs-comment">// 根据开发模式,自动判断是否使用index.html中的CDN</span></span>
  config<span class="token punctuation">.</span><span class="token function">plugin</span><span class="token punctuation">(</span><span class="token string"><span class="hljs-string">'html'</span></span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">tap</span><span class="token punctuation">(</span><span class="hljs-function"><span class="hljs-params">args</span> </span><span class="token operator"><span class="hljs-function">=&gt;</span></span> <span class="token punctuation">{</span>
    <span class="token comment"><span class="hljs-comment">// 这里的title是index.html中的title的lodash模板变量的参数</span></span>
    args<span class="token punctuation">[</span><span class="token number"><span class="hljs-number">0</span></span><span class="token punctuation">]</span><span class="token punctuation">.</span>title <span class="token operator">=</span> <span class="token string"><span class="hljs-string">"dev模式 - 超级商城后台管理"</span></span>
    <span class="token comment"><span class="hljs-comment">// 是否是生产模式</span></span>
    args<span class="token punctuation">[</span><span class="token number"><span class="hljs-number">0</span></span><span class="token punctuation">]</span><span class="token punctuation">.</span>isProd <span class="token operator">=</span> <span class="token boolean"><span class="hljs-literal">false</span></span>
    <span class="hljs-built_in">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span>  <span class="token comment"><span class="hljs-comment">//args中包含当前plugin配置的参数</span></span>
    <span class="token comment"><span class="hljs-comment">// 注意最后要把数组返回</span></span>
    <span class="token keyword"><span class="hljs-keyword">return</span></span> args
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

}
}

args中包含当前plugin配置的参数,其打印出结果如下。

 config.plugin('html').tap(args => {
        // 这里的title是index.html中的title的lodash模板变量的参数
        args[0].title = "dev模式 - 超级商城后台管理"
        // 是否是生产模式
        args[0].isProd=false
        console.log(args)  //args中包含当前plugin配置的参数
        // 注意最后要把数组返回
        return args
      })
[
  {
    title: 'dev模式 - 超级商城后台管理',
    templateParameters: [Function: templateParameters],
    template: 'D:\\Users\\王金龙\\Desktop\\shop_manage\\public\\index.html',
    isProd: false
  }
]
prod.env.js

既然增加了自动判断是否引入CDN那么引入本地的代码就注释/删掉,根据配置(如果在开发阶段就使用dev.env.js,生产阶段就使用的是 prod.env.js

// import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false

// import ElementUI from ‘element-ui’;
// import ‘element-ui/lib/theme-chalk/index.css’;
// Vue.use(ElementUI);

// import request from “./network/request”
// Vue.prototype.$http = request

// import axios from “axios”
axios.defaults.baseURL=‘http://127.0.0.1:8888/api/private/v1/’
// 请求拦截
axios.interceptors.request.use(config=>{
config.headers.Authorization=sessionStorage.getItem(‘token’)
// console.log(config);
return config
})
// 响应拦截
axios.interceptors.response.use(res=>{
return res.data
})
Vue.prototype.$http = axios

// 字体图标
import ‘./assets/font/iconfont.css’

// 时间格式化
// import moment from “moment”
// 全局的时间格式过滤器
Vue.filter(‘formatTime’, v => {
return moment.unix(v / 1000).format(‘YYYY-MM-DD HH:mm:SS’)
})

// 富文本
// import VueQuillEditor from ‘vue-quill-editor’
// // require styles
// import ‘quill/dist/quill.core.css’
// import ‘quill/dist/quill.snow.css’
// import ‘quill/dist/quill.bubble.css’
// 使用CSN方式使用插件,use不能省略,还需要使用use使用改插件
Vue.use(VueQuillEditor)

new Vue({
router,
render: h => h(App)
}).$mount(’#app’)

dev.env.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false

import ElementUI from ‘element-ui’;
import ‘element-ui/lib/theme-chalk/index.css’;
Vue.use(ElementUI);

// import request from “./network/request”
// Vue.prototype.$http = request

import axios from “axios”
axios.defaults.baseURL=‘http://127.0.0.1:8888/api/private/v1/’
// 请求拦截
axios.interceptors.request.use(config=>{
config.headers.Authorization=sessionStorage.getItem(‘token’)
// console.log(config);
return config
})
// 响应拦截
axios.interceptors.response.use(res=>{
return res.data
})
Vue.prototype.$http = axios

// 字体图标
import ‘./assets/font/iconfont.css’

// 时间格式化
// import moment from “moment”
// 全局的时间格式过滤器
Vue.filter(‘formatTime’, v => {
return moment.unix(v / 1000).format(‘YYYY-MM-DD HH:mm:SS’)
})

// 富文本
import VueQuillEditor from ‘vue-quill-editor’
// require styles
import ‘quill/dist/quill.core.css’
import ‘quill/dist/quill.snow.css’
import ‘quill/dist/quill.bubble.css’
// 使用CSN方式使用插件,use不能省略,还需要使用use使用改插件
Vue.use(VueQuillEditor)

new Vue({
router,
render: h => h(App)
}).$mount(’#app’)

优化之路由懒加载

https://router.vuejs.org/zh/guide/advanced/lazy-loading.html

const Foo = () => import('./Foo.vue')

在路由配置中什么都不需要改变,只需要像往常一样使用 Foo

const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})

把组件按组分块

有时候我们想把某个路由下的所有组件都打包在同个异步块 (chunk) 中。只需要使用 命名 chunk,一个特殊的注释语法来提供 chunk name (需要 Webpack > 2.4)。

const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

Webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中。

还有就是后端支持http2.0 配置ng就可以了

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值