多页vue应用的单页面打包方法(内含打包模式的应用)


Posted in Javascript onJune 11, 2020

一、简介

关于如何以及为什么要构建多页vue应用,我们在上一篇文章中已经介绍过,感兴趣的请参考构建多页vue应用。本文我们要介绍的是,对于一个多页应用,如何单独打包其中一个(或几个)页面。

一般来说,多页应用不需要打包单个页面,这多个页面可以作为整个应用直接放在静态资源服务器上。不过我们也说过,多页应用的每个页面也可能会放在不同的服务器上,这时候如果往每个服务器上都放置完整的资源包,就会显得过于臃肿。于是我们可能就需要将某个页面单独打包出来。

诚然,有一个很明显的方法,就是在每次打包的时候直接删掉vue.config.js的pages字段里不相关的页面,如:

module.exports = {
 pages: {
  page1: {...},
  // page2: {...},
  // page3: {...}
 }
}

显然,这样打包出来的结果就是只有page1页面了。

但是每次打包都删改配置文件并不是一种很优雅的做法。我们需要的方案是有多个打包命令,执行对应的打包命令即可打包对应的页面,这样我们就可以不再改配置文件了。下面我们来介绍这种方法:

二、实现过程

要实现通过不同的打包命令来打包单独的页面,需要先从打包命令本身说起。

1. 配置打包指令(指定打包模式)

我们执行的打包命令为npm run build,这个命令执行的是package.json的scripts字段下的build命令,它的原始值如下:

{
 ...
 "scripts": {
  ...
  "build": "vue-cli-service build"
 }
 ...
}

也就是说,这个命令实际上是在调用vue-cli-service服务的build命令。

根据vue-cli的文档介绍,build命令后面可以跟一个mode参数,定义打包模式,默认的打包模式包括production、development和test三个,它们的行为主要是把全局的process.env.NODE_ENV变量置为对应的值(即production、development和test)。在省略mode参数的情况下,默认值是production,即生产模式。

除了这三个默认模式外,我们还可以自定义打包模式。假如我们想定义一个专门打包page1的打包模式,就可以这样一个指令:

"scripts": {
  "build-page1": "vue-cli-service build --mode page1"
 }

我们希望,当执行npm run build-page1命令时,webpack就会自动把page1打包出来。

但显然只修改这里是不够的,webpack并不知道page1是什么模式,以及它应该有哪些行为。接下来我们需要为page1这个打包模式定义行为。

2. 定义模式行为

启用一个打包模式的本质含义,其实是启用一组特定的环境变量。

比如,production模式会把process.env.NODE_ENV的值置为production,而process.env是webpack所在的node环境提供的全局变量。这样,在代码中,只需要根据process.env.NODE_ENV的值就可以判断当前处于哪种打包模式了,代码可以根据不同的打包模式产生不同的行为。

对于自定义的打包模式,我们也可以指定一组全局变量,以使代码产生不同的行为。vue-cli文档规定,每个自定义模式对应的变量应该定义在根目录下的.env.xxx文件内。比如我们的打包模式名为page1,那么就需要在项目根目录下新建一个.env.page1(注意,这里是没有后缀的)文件:

多页vue应用的单页面打包方法(内含打包模式的应用)

当指定打包模式为page1时,webpack就会启用这个文件中所定义的变量。文件内可以这样定义变量:
.env.page1

NODE_ENV = 'production'
page = 'page1'

现在,当使用打包模式page1时,webpack就会读取这个环境文件,然后把这里定义的变量逐个添加到全局对象process.env上。因此此时process.env.page的值就是字符串'page1'(NODE_ENV的值默认就是production,这里可以省略)。

向全局变量注册了变量page之后,我们就可以在程序中根据它定义打包行为了。

3. 定义打包逻辑

之前我们定义多页应用的配置时,pages字段配置的是固定的值,也就是定义了三个打包入口。现在有了全局变量process.env.page,我们就不需要设为定值了,而是可以根据这个变量的值,动态定义打包入口。此时vue.config.js可以进行如下改造:

function resolvePages(page){
 let page1 = {
  entry: 'src/pages/page1/main.js',
  template: 'public/index.html',
  filename: 'page1.html',
 };
 let page2 = {
  entry: 'src/pages/page2/main.js',
  template: 'public/index.html',
  filename: 'page2.html',
 };
 let page3 = {
  entry: 'src/pages/page3/main.js',
  template: 'public/index.html',
  filename: 'page3.html',
 };
 return page === 'page1' ? { page1 } : 
  { page1, page2, page3 };
}
module.exports = {
 pages: resolvePages(process.env.page),
}

我们现在读取process.env.page的值进行判断,如果它的值是page1,那么说明我们处于page1打包模式下,于是resolvePages函数返回的对象仅包括page1这一个页面的入口,否则就返回三个打包入口,进行完整多页应用的构建。

基于这个原理,我们同样可以定义page2、page3的打包模式,甚至定义更加复杂的打包模式(如同时打包page1和page2),此时resolvePages函数的返回值只是稍微复杂一些:

return page === 'page1' ? { page1 } : 
 page === 'page2' ? { page2 } : 
 page === 'page1,page2' ? { page1, page2 } :
 ...
 { page1, page2, page3 };

现在一切准备就绪。

我们执行npm run build-page1命令时,vue-cli会先读取指定的page1模式对应的.env.page1文件,它会为process.env新增环境变量page。然后vue-cli会去读取vue.config.js配置文件中的pages字段,调用resolvePages函数,并传入变量process.env.page,得到打包入口对象为:{ page1 },由于只有一个打包入口,因此vue-cli会调用webpack的打包服务,对该页面进行单独构建。

有人可能会问,难道只有打包时才能指定mode吗?其实不是的,serve命令也有mode参数。根据以上过程,你也可以单独启动某一个页面,此时你只需要定义下面这样的脚本:

{
 ...
 "scripts": {
  "serve-page1": "vue-cli-service serve --mode page1"
 }
}

与打包过程没有什么差别,这里就不再赘述了。

需要注意的是,public文件夹下的资源是静态资源,无论使用任何打包模式,它们都会被直接拷贝到dist文件夹下。

三、打包模式的应用

打包模式的应用不仅在于单页打包,我们举一个更常见的例子:假设我们的代码打包后可能被派发到多个项目上,而这些项目之间却存在一些细小的差别(比如某个表格的样式不同)。如果我们为每个项目都单独创建一份代码,那么代码库将变得极难维护。这时候,打包模式就可以派上用场了。

我们可以为这些项目分别创建单独的打包命令,如:

{
 "scripts": {
  "build-project1": "vue-cli-service build --mode project1",
  "build-project2": "vue-cli-service build --mode project2",
 }
}

然后在根目录下分别为每个打包模式定义一个环境文件:.env.project1,.env.project2。我们在这里分别定义一组全局变量:
.env.project1

VUE_APP_PROJECT = 'project1'

.env.project2

VUE_APP_PROJECT = 'project2'

这里需要强调的是,如果需要在src路径下的代码中引用env中的某个变量,那么这个变量必须以VUE_APP_开头,否则结果都会是undefined(在src之外的代码中没有这个限制,如上面我们在vue.config.js中引用的变量就没有遵循这个约束,当然你可以更规范地对所有自定义变量添加这个前缀,以防止出错)。

现在,当执行npm run build-project1时,process.env.VUE_APP_PROJECT的值就是project1,我们可以在代码中根据这个值来区分不同的项目。比如在某个组件中,我们需要对项目1添加一些额外的逻辑:

methods: {
 doSomething(){
  if(process.env.VUE_APP_PROJECT === 'project1'){
   // 对project1项目添加额外的逻辑
   ...
  }
 }
}

当你运行npm run build-project1打包命令时,if语句的内容就会生效,反之,在其他模式下,它不会生效。同样的,你也可以配置项目1专属的启动命令:

"serve-project1": "vue-cli-service serve --mode project1"

你可以运行npm run serve-project1来启用project1环境。

总结

通过学习在多页应用中打包单个页面,我们学会了如何自定义打包模式,这应该是本文最重要的知识点。将打包模式推广,我们学会了如何在一份代码中添加多个项目的逻辑,这使得我们维护多个项目分支的成本大大降低。打包模式的用途可能还远不止这些,希望读者理解它,并熟练运用。

到此这篇关于多页vue应用的单页面打包方法(内含打包模式的应用)的文章就介绍到这了,更多相关多页vue应用的单页面打包内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
Extjs实现进度条的两种便捷方式
Sep 26 Javascript
JS获取月的最后一天与JS得到一个月份最大天数的实例代码
Dec 16 Javascript
javascript删除数组元素并且数组长度减小的简单实例
Feb 14 Javascript
Backbone.js框架中Model与Collection的使用实例
May 07 Javascript
微信小程序开发(一) 微信登录流程详解
Jan 11 Javascript
微信小程序滚动Tab实现左右可滑动切换
Aug 17 Javascript
JS小球抛物线轨迹运动的两种实现方法详解
Dec 20 Javascript
使用Vue自定义指令实现Select组件
May 24 Javascript
vue项目设置scrollTop不起作用(总结)
Dec 21 Javascript
countUp.js实现数字滚动效果
Oct 18 Javascript
JQuery 实现文件下载的常用方法分析
Oct 29 jQuery
JavaScript架构localStorage特殊场景下二次封装操作
Jun 21 Javascript
VUE页面中通过双击实现复制表格中内容的示例代码
Jun 11 #Javascript
vue scroll滚动判断的实现(是否滚动到底部、滚动方向、滚动节流、获取滚动区域dom元素)
Jun 11 #Javascript
Vue初始化中的选项合并之initInternalComponent详解
Jun 11 #Javascript
Vue组件为什么data必须是一个函数
Jun 11 #Javascript
Vue实现点击箭头上下移动效果
Jun 11 #Javascript
webpack+express实现文件精确缓存的示例代码
Jun 11 #Javascript
详解vue 组件
Jun 11 #Javascript
You might like
php站内搜索关键词变亮的实现方法
2014/12/30 PHP
php+mysqli事务控制实现银行转账实例
2015/01/29 PHP
Laravel框架在本地虚拟机快速安装的方法详解
2018/06/11 PHP
JS、DOM和JQuery之间的关系示例分析
2014/04/09 Javascript
jquery实现鼠标拖拽滑动效果来选择数字的方法
2015/05/04 Javascript
jQuery+css实现的蓝色水平二级导航菜单效果代码
2015/09/11 Javascript
JS实现来回出现文字的状态栏特效代码
2015/10/31 Javascript
BootStrap日期控件在模态框中选择时间下拉菜单无效的原因及解决办法(火狐下不能点击)
2016/08/18 Javascript
微信小程序(应用号)开发新闻客户端实例
2016/10/24 Javascript
jQuery解析返回的xml和json方法详解
2017/01/05 Javascript
将angular-ui的分页组件封装成指令的方法详解
2017/05/10 Javascript
用纯Node.JS弹出Windows系统消息提示框实例(MessageBox)
2017/05/17 Javascript
基于nodejs+express4.X实现文件下载的实例代码
2017/07/13 NodeJs
Angular4.0中引入laydate.js日期插件的方法教程
2017/12/25 Javascript
微信小程序用户授权,以及判断登录是否过期的方法
2019/05/10 Javascript
vue draggable resizable gorkys与v-chart使用与总结
2019/09/05 Javascript
JavaScript变量基本使用方法实例分析
2019/11/15 Javascript
vue移动端使用appClound拉起支付宝支付的实现方法
2019/11/21 Javascript
跟老齐学Python之有点简约的元组
2014/09/24 Python
12步教你理解Python装饰器
2016/02/25 Python
Python中如何优雅的合并两个字典(dict)方法示例
2017/08/09 Python
高效使用Python字典的清单
2018/04/04 Python
python使用folium库绘制地图点击框
2018/09/21 Python
Django模板Templates使用方法详解
2019/07/19 Python
python使用Matplotlib改变坐标轴的默认位置
2019/10/18 Python
python selenium xpath定位操作
2020/09/01 Python
最新PyCharm 2020.2.3永久激活码(亲测有效)
2020/11/26 Python
python 将html转换为pdf的几种方法
2020/12/29 Python
印度网上药店:1mg
2017/10/13 全球购物
大学生个人事迹材料
2014/01/21 职场文书
运动会稿件300字
2014/02/14 职场文书
五好关工委申报材料
2014/05/31 职场文书
力学专业求职信
2014/07/23 职场文书
平安工地汇报材料
2014/08/19 职场文书
世界红十字日活动总结
2015/02/10 职场文书
小学生红领巾广播稿
2015/08/19 职场文书