多页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_07_理解instanceof实现原理
Oct 15 Javascript
js 金额格式化来回转换示例
Feb 23 Javascript
javascript操作select元素实例分析
Mar 27 Javascript
confirm确认对话框的实现方法总结
Jun 17 Javascript
浅谈js的ajax的异步和同步请求的问题
Oct 07 Javascript
jQuery EasyUI ProgressBar进度条组件
Feb 28 Javascript
js实现自动图片轮播代码
Mar 22 Javascript
NW.js 简介与使用方法
Feb 01 Javascript
详解Vue取消eslint语法限制
Aug 04 Javascript
利用js将ajax获取到的后台数据动态加载至网页中的方法
Aug 08 Javascript
前后端常见的几种鉴权方式(小结)
Aug 04 Javascript
vue 子组件修改data或调用操作
Aug 07 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
一个可查询所有表的“通用”查询分页类
2006/10/09 PHP
整合了前面的PHP数据库连接类~~做成一个分页类!
2006/11/25 PHP
isset和empty的区别
2007/01/15 PHP
php下关于Cannot use a scalar value as an array的解决办法
2010/08/08 PHP
PHP编程开发怎么提高编程效率 提高PHP编程技术
2015/11/09 PHP
php自定义时间转换函数示例
2016/12/07 PHP
jQuery 位置函数offset,innerWidth,innerHeight,outerWidth,outerHeight,scrollTop,scrollLeft
2010/03/23 Javascript
JSQL SQLProxy 的 php 版本代码
2010/05/05 Javascript
jquery清空表单数据示例分享
2014/02/13 Javascript
Jquery.Form 异步提交表单的简单实例
2014/03/03 Javascript
JavaScript中的prototype和constructor简明总结
2014/04/05 Javascript
jQuery中after()方法用法实例
2014/12/25 Javascript
深入理解JavaScript系列(42):设计模式之原型模式详解
2015/03/04 Javascript
jQuery使用$.each遍历json数组的简单实现方法
2016/04/18 Javascript
ECMAScript6轮播图实践知识总结
2016/08/17 Javascript
js实现文字无缝向上滚动
2017/02/16 Javascript
node.js操作mongodb简单示例分享
2017/05/25 Javascript
详解Vue.js之视图和数据的双向绑定(v-model)
2017/06/23 Javascript
利用vue组件自定义v-model实现一个Tab组件方法示例
2017/12/06 Javascript
基于vue.js 2.x的虚拟滚动条的示例代码
2018/01/23 Javascript
vue中前进刷新、后退缓存用户浏览数据和浏览位置的实例讲解
2018/09/21 Javascript
Koa 使用小技巧(小结)
2018/10/22 Javascript
Vue打包后访问静态资源路径问题
2019/11/08 Javascript
Python基于分水岭算法解决走迷宫游戏示例
2017/09/26 Python
用TensorFlow实现多类支持向量机的示例代码
2018/04/28 Python
python绘制漏斗图步骤详解
2019/03/04 Python
Python利用pandas处理Excel数据的应用详解
2019/06/18 Python
对python 调用类属性的方法详解
2019/07/02 Python
python mysql自增字段AUTO_INCREMENT值的修改方式
2020/05/18 Python
经济职业学院毕业生自荐书
2014/03/17 职场文书
2014年教师节国旗下讲话稿
2014/09/10 职场文书
敲诈同学钱财检讨书范文
2014/11/18 职场文书
react 项目中引入图片的几种方式
2021/06/02 Javascript
SpringDataJPA在Entity中常用的注解介绍
2021/12/06 Java/Android
Java设计模式之享元模式示例详解
2022/03/03 Java/Android
CSS实现背景图片全屏铺满自适应的3种方式
2022/07/07 HTML / CSS