多页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 相关文章推荐
Javascript实现的分页函数
Feb 07 Javascript
jQuery Flash/MP3/Video多媒体插件
Jan 18 Javascript
JS对img进行操作(换图片/切图/轮换/停止)
Apr 17 Javascript
jquery ajax同步异步的执行最终解决方案
Apr 26 Javascript
关于JS中的闭包浅谈
Aug 23 Javascript
GitHub上一些实用的JavaScript的文件压缩解压缩库推荐
Mar 13 Javascript
js实现九宫格的随机颜色跳转
Feb 19 Javascript
利用adb shell和node.js实现抖音自动抢红包功能(推荐)
Feb 22 Javascript
React props和state属性的具体使用方法
Apr 12 Javascript
vue-auto-focus: 控制自动聚焦行为的 vue 指令方法
Aug 25 Javascript
Vue.js的复用组件开发流程完整记录
Nov 29 Javascript
Vue.js实现大屏数字滚动翻转效果
Nov 29 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 各种应用乱码问题的解决方法
2010/05/09 PHP
Zend Framework动作助手Redirector用法实例详解
2016/03/05 PHP
php读取XML的常见方法实例总结
2017/04/25 PHP
tp5.1 框架查询表达式用法详解
2020/05/25 PHP
谈谈关于JavaScript 中的 MVC 模式
2013/04/11 Javascript
JQuery AJAX 中文乱码问题解决
2013/06/05 Javascript
js获取当前日期时间及其它操作汇总
2015/04/17 Javascript
JavaScript统计网站访问次数的实现代码
2015/11/18 Javascript
WebApi+Bootstrap+KnockoutJs打造单页面程序
2016/05/16 Javascript
Bootstrap表单Form全面解析
2016/06/13 Javascript
javascript计算渐变颜色的实例
2017/09/22 Javascript
简单实现vue验证码60秒倒计时功能
2017/10/11 Javascript
swiper移动端轮播插件(触碰图片之后停止轮播)
2017/12/28 Javascript
JavaScript累加、迭代、穷举、递归等常用算法实例小结
2018/05/08 Javascript
基于Vue实现电商SKU组合算法问题
2019/05/29 Javascript
微信小游戏中three.js离屏画布的示例代码
2020/10/12 Javascript
Vue.js桌面端自定义滚动条组件之美化滚动条VScroll
2020/12/01 Vue.js
仅用50行代码实现一个Python编写的计算器的教程
2015/04/17 Python
利用Python实现颜色色值转换的小工具
2016/10/27 Python
Python进阶_关于命名空间与作用域(详解)
2017/05/29 Python
Python随机生成手机号、数字的方法详解
2017/07/21 Python
Python计算不规则图形面积算法实现解析
2019/11/22 Python
总结Pyinstaller的坑及终极解决方法(小结)
2020/09/21 Python
详解pycharm的python包opencv(cv2)无代码提示问题的解决
2021/01/29 Python
如何用 Python 制作一个迷宫游戏
2021/02/25 Python
CSS3 3D制作实战案例分析
2016/09/18 HTML / CSS
HTML5 placeholder属性详解
2016/06/22 HTML / CSS
html5+svg学习指南之SVG基础知识
2014/12/17 HTML / CSS
办公室主任职责范文
2013/11/08 职场文书
机械专业应届生求职信
2013/12/12 职场文书
日化店促销方案
2014/03/26 职场文书
老师对学生的寄语
2014/04/09 职场文书
媒体宣传策划方案
2014/05/25 职场文书
2014年酒店服务员工作总结
2014/12/08 职场文书
学前班学生评语
2014/12/29 职场文书
为什么RedisCluster设计成16384个槽
2021/09/25 Redis