多页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动态调整iframe高度的方法
Mar 06 Javascript
新浪中用来显示flash的函数
Apr 02 Javascript
基于jQuery的图片大小自动适应实现代码
Nov 17 Javascript
一个网页标题title的闪动提示效果实现思路
Mar 22 Javascript
jQuery处理图片加载失败的常用方法
Jun 08 Javascript
JS实现用户注册时获取短信验证码和倒计时功能
Oct 27 Javascript
JavaScript的setter与getter方法
Nov 29 Javascript
JS实现匀速与减速缓慢运动的动画效果封装示例
Aug 27 Javascript
vue 循环加载数据并获取第一条记录的方法
Sep 26 Javascript
微信小程序之裁剪图片成圆形的实现代码
Oct 11 Javascript
使用mixins实现elementUI表单全局验证的解决方法
Apr 02 Javascript
js将URL网址转为16进制加密与解密函数
Mar 04 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调用Linux命令权限不足问题解决方法
2015/02/07 PHP
在WordPress中使用wp_count_posts函数来统计文章数量
2016/01/05 PHP
php求今天、昨天、明天时间戳的简单实现方法
2016/07/28 PHP
Js动态创建div
2008/09/25 Javascript
HTML node相关的一些资料整理
2010/01/01 Javascript
改善你的jQuery的25个步骤 千倍级效率提升
2010/02/11 Javascript
IE无法设置短域名下Cookie
2010/09/23 Javascript
容易被忽略的JS脚本特性
2011/09/13 Javascript
extjs 04_grid 单击事件新发现
2012/11/27 Javascript
JQuery 中几个类选择器的简单使用介绍
2013/03/14 Javascript
使用js声明数组,对象在jsp页面中(获得ajax得到json数据)
2013/11/05 Javascript
JQuery实现当鼠标停留在某区域3秒后自动执行
2014/09/09 Javascript
jQuery中slideUp()方法用法分析
2014/12/24 Javascript
jQuery的三种bind/One/Live/On事件绑定使用方法
2017/02/23 Javascript
Vuejs 页面的区域化与组件封装的实现
2017/09/11 Javascript
javaScript实现鼠标在文字上悬浮时弹出悬浮层效果
2020/04/12 Javascript
Vue-cli@3.0 插件系统简析
2018/09/05 Javascript
js实现点击展开隐藏效果(实例代码)
2018/09/28 Javascript
小程序实现页面顶部选项卡效果
2018/11/06 Javascript
javascript的hashCode函数实现代码小结
2020/08/11 Javascript
Vuex实现购物车小功能
2020/08/17 Javascript
夯基础之手撕javascript继承详解
2020/11/09 Javascript
python图书管理系统
2020/04/05 Python
Python之NumPy(axis=0 与axis=1)区分详解
2019/05/27 Python
Python操作Excel工作簿的示例代码(\*.xlsx)
2020/03/23 Python
python音频处理的示例详解
2020/12/23 Python
python urllib和urllib3知识点总结
2021/02/08 Python
英国最大的电子产品和家电零售企业:Currys PC World
2016/09/24 全球购物
美国滑雪板和装备购物网站:Skis.com
2018/12/20 全球购物
租房协议书范本
2014/04/09 职场文书
本科生求职信
2014/06/17 职场文书
求职自我推荐信
2015/03/24 职场文书
英文自荐信范文
2015/03/25 职场文书
春季运动会加油词
2015/07/18 职场文书
Python 游戏大作炫酷机甲闯关游戏爆肝数千行代码实现案例进阶
2021/10/16 Python
Node.js实现爬取网站图片的示例代码
2022/04/04 NodeJs