多页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 相关文章推荐
jQuery textarea的长度进行验证
May 06 Javascript
ASP.NET jQuery 实例8 (动态添加内容到DropDownList)
Feb 03 Javascript
文本有关的样式和jQuery求对象的高宽问题分别说明
Aug 30 Javascript
JQEasy-ui在IE9以下版本中二次加载的问题分析及处理方法
Jun 23 Javascript
node.js中的fs.lchmod方法使用说明
Dec 16 Javascript
Javascript实现计算个人所得税
May 10 Javascript
快速获取/设置iframe内对象元素的几种js实现方法
May 20 Javascript
JavaScript实现的鼠标响应颜色渐变效果完整实例
Feb 18 Javascript
DataTables添加额外的查询参数和删除columns等无用参数实例
Jul 04 Javascript
JS正则表达式完美实现身份证校验功能
Oct 18 Javascript
vue2使用keep-alive缓存多层列表页的方法
Sep 21 Javascript
vuex管理状态 刷新页面保持不被清空的解决方案
Nov 11 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使用curl存储cookie的示例
2014/03/31 PHP
php自定义函数实现二维数组排序功能
2016/07/20 PHP
php 输入输出流详解及示例代码
2016/08/25 PHP
[企业公众号]升级到[企业微信]之后发送消息失败的解决方法
2017/06/30 PHP
laravel5.4利用163邮箱发送邮件的步骤详解
2017/09/22 PHP
javascript与CSS复习(二)
2010/06/29 Javascript
初识JQuery 实例一(first)
2011/03/16 Javascript
jquery 元素控制(追加元素/追加内容)介绍及应用
2013/04/21 Javascript
js控制web打印(局部打印)方法整理
2013/05/29 Javascript
JavaScript中SetInterval与setTimeout的用法详解
2015/11/10 Javascript
浅析JavaScript中的对象类型Object
2016/05/26 Javascript
从零学习node.js之简易的网络爬虫(四)
2017/02/22 Javascript
bootstrap3-dialog-master模态框使用详解
2017/08/22 Javascript
js实现登录注册框手机号和验证码校验(前端部分)
2017/09/28 Javascript
从parcel.js打包出错到选择nvm的全部过程
2018/01/23 Javascript
Angular短信模板校验代码
2020/09/23 Javascript
[41:17]完美世界DOTA2联赛PWL S3 access vs CPG 第二场 12.13
2020/12/17 DOTA
Flask框架学习笔记(一)安装篇(windows安装与centos安装)
2014/06/25 Python
在Lighttpd服务器中运行Django应用的方法
2015/07/22 Python
MySQL适配器PyMySQL详解
2017/09/20 Python
Python设计模式之外观模式实例详解
2019/01/17 Python
python3使用matplotlib绘制条形图
2020/03/25 Python
python生成requirements.txt的两种方法
2019/09/18 Python
Python docutils文档编译过程方法解析
2020/06/23 Python
python实现图像外边界跟踪操作
2020/07/13 Python
可以随进度显示不同颜色的css3进度条分享
2014/04/11 HTML / CSS
目前不被任何主流浏览器支持的CSS3属性汇总
2014/07/21 HTML / CSS
马来西亚银饰品牌:JEOEL
2017/12/15 全球购物
英国鹦鹉店:Parrot Essentials
2018/12/03 全球购物
马来西亚太阳镜、眼镜和隐形眼镜网上商店:Focus Point
2018/12/13 全球购物
工商学院毕业生自荐信
2013/11/12 职场文书
退伍老兵事迹材料
2014/01/31 职场文书
十佳家长事迹材料
2014/08/26 职场文书
2014年绿化工作总结
2014/12/09 职场文书
加入学生会自荐书
2015/03/05 职场文书
计划生育目标责任书
2015/05/09 职场文书