Vue CLI3基础学习之pages构建多页应用


Posted in Javascript onJune 02, 2019

前言

首先我们可以把多页应用理解为由多个单页构成的应用,而何谓多个单页呢?其实你可以把一个单页看成是一个 html 文件,那么多个单页便是多个 html 文件,多页应用便是由多个 html 组成的应用,如下图所示

Vue CLI3基础学习之pages构建多页应用

既然多页应用拥有多个 html ,那么同样其应该拥有多个独立的入口文件、组件、路由、 vuex 等。没错,说简单一点就是多页应用的每个单页都可以拥有单页应用 src 目录下的文件及功能,我们来看一下一个基础多页应用的目录结构

├── node_modules               # 项目依赖包目录
├── build                      # 项目 webpack 功能目录
├── config                     # 项目配置项文件夹
├── src                        # 前端资源目录
│   ├── images                 # 图片目录
│   ├── components             # 公共组件目录
│   ├── pages                  # 页面目录
│   │   ├── page1              # page1 目录
│   │   │   ├── components     # page1 组件目录
│   │   │   ├── router         # page1 路由目录
│   │   │   ├── views          # page1 页面目录
│   │   │   ├── page1.html     # page1 html 模板
│   │   │   ├── page1.vue      # page1 vue 配置文件
│   │   │   └── page1.js       # page1 入口文件
│   │   ├── page2              # page2 目录
│   │   └── index              # index 目录
│   ├── common                 # 公共方法目录
│   └── store                  # 状态管理 store 目录
├── .gitignore                 # git 忽略文件
├── .env                       # 全局环境配置文件
├── .env.dev                   # 开发环境配置文件
├── .postcssrc.js              # postcss 配置文件
├── babel.config.js            # babel 配置文件
├── package.json               # 包管理文件
├── vue.config.js              # CLI 配置文件
└── yarn.lock                  # yarn 依赖信息文件

二、多入口

在单页应用中,我们的入口文件只有一个, CLI 默认配置的是 main.js ,但是到了多页应用,我们的入口文件便包含了 page1.js 、 page2.js 、 index.js 等,数量取决于 pages 文件夹下目录的个数,这时候为了项目的可拓展性,我们需要自动计算入口文件的数量并解析路径配置到 webpack 中的 entry 属性上,如:

module.exports = {
 ...
 
 entry: {
  page1: '/xxx/pages/page1/page1.js',
  page2: '/xxx/pages/page2/page2.js',
  index: '/xxx/pages/index/index.js',
 },
 
 ...
}

那么我们如何读取并解析这样的路径呢,这里就需要使用工具和函数来解决了。我们可以在根目录新建 build 文件夹存放 utils.js 这样共用的 webpack 功能性文件,并加入多入口读取解析方法

/* utils.js */
const path = require('path');

// glob 是 webpack 安装时依赖的一个第三方模块,该模块允许你使用 * 等符号,
// 例如 lib/*.js 就是获取 lib 文件夹下的所有 js 后缀名的文件
const glob = require('glob');

// 取得相应的页面路径,因为之前的配置,所以是 src 文件夹下的 pages 文件夹
const PAGE_PATH = path.resolve(__dirname, '../src/pages');

/* 
* 多入口配置
* 通过 glob 模块读取 pages 文件夹下的所有对应文件夹下的 js * 后缀文件,如果该文件存在
* 那么就作为入口处理
*/
exports.getEntries = () => {
 let entryFiles = glob.sync(PAGE_PATH + '/*/*.js') // 同步读取所有入口文件
 let map = {}
 
 // 遍历所有入口文件
 entryFiles.forEach(filePath => {
  // 获取文件名
  let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
  
  // 以键值对的形式存储
  map[filename] = filePath 
 })
 
 return map
}

Vue CLI3基础学习之pages构建多页应用

读取并存储完毕后,我们得到了一个入口文件的对象集合,这个对象我们便可以将其设置到 webpack 的 entry 属性上,这里我们需要修改 vue.config.js 的配置来间接修改 webpack 的值

/* vue.config.js */

const utils = require('./build/utils')

module.exports = {
 ...
 
 configureWebpack: config => {
  config.entry = utils.getEntries()
 },
 
 ...
}

这样我们多入口的设置便完成了,当然这并不是 CLI 所希望的操作,后面我们会进行改进。

三、多模板

相对于多入口来说,多模板的配置也是大同小异,这里所说的模板便是每个 page 下的 html 模板文件,而模板文件的作用主要用于 webpack 中 html-webpack-plugin 插件的配置,其会根据模板文件生产一个编译后的 html 文件并自动加入携带 hash 的脚本和样式,基本配置如下

/* webpack 配置文件 */
const HtmlWebpackPlugin = require('html-webpack-plugin') // 安装并引用插件

module.exports = {
 ...
 
 plugins: [
  new HtmlWebpackPlugin({
   title: 'My Page', // 生成 html 中的 title
   filename: 'demo.html', // 生成 html 的文件名
   template: 'xxx/xxx/demo.html', // 模板路径
   chunks: ['manifest', 'vendor', 'demo'], // 所要包含的模块
   inject: true, // 是否注入资源
  })
 ]
 
 ...
}

以上是单模板的配置,那么如果是多模板只要继续往 plugins 数组中添加 HtmlWebpackPlugin 即可,但是为了和多入口一样能够灵活的获取 pages 目录下所有模板文件并进行配置,我们可以在 utils.js 中添加多模板的读取解析方法

/* utils.js */

// 多页面输出配置
// 与上面的多页面入口配置相同,读取 page 文件夹下的对应的 html 后缀文件,然后放入数组中
exports.htmlPlugin = configs => {
 let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')
 let arr = []
 
 entryHtml.forEach(filePath => {
  let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
  let conf = {
   template: filePath, // 模板路径
   filename: filename + '.html', // 生成 html 的文件名
   chunks: ['manifest', 'vendor', filename],
   inject: true,
  }
  
  // 如果有自定义配置可以进行 merge
  if (configs) {
   conf = merge(conf, configs)
  }
  
  // 针对生产环境配置
  if (process.env.NODE_ENV === 'production') {
   conf = merge(conf, {
    minify: {
     removeComments: true, // 删除 html 中的注释代码
     collapseWhitespace: true, // 删除 html 中的空白符
     // removeAttributeQuotes: true // 删除 html 元素中属性的引号
    },
    chunksSortMode: 'manual' // 按 manual 的顺序引入
   })
  }
  
  arr.push(new HtmlWebpackPlugin(conf))
 })
 
 return arr
}

Vue CLI3基础学习之pages构建多页应用

  • 以上我们仍然是使用 glob 读取所有模板文件,然后将其遍历并设置每个模板的 config ,同时针对一些自定义配置和生产环境的配置进行了 merge 处理,其中自定义配置的功能我会在下节进行介绍,这里介绍一下生产环境下 minify 配置的作用:将 html-minifier 的选项作为对象来缩小输出。
  • html-minifier 是一款用于缩小 html 文件大小的工具,其有很多配置项功能,包括上述所列举的常用的删除注释、空白、引号等。
  • 当我们编写完了多模板的方法后,我们同样可以在 vue.config.js 中进行配置,与多入口不同的是我们在 configureWebpack 中不能直接替换 plugins 的值,因为它还包含了其他插件
/* vue.config.js */

const utils = require('./build/utils')

module.exports = {
 ...
 
 configureWebpack: config => {
  config.entry = utils.getEntries() // 直接覆盖 entry 配置
  
  // 使用 return 一个对象会通过 webpack-merge 进行合并,plugins 不会置空
  return {
   plugins: [...utils.htmlPlugin()]
  }
 },
 
 ...
}

如此我们多页应用的多入口和多模板的配置就完成了,这时候我们运行命令 yarn build 后你会发现 dist 目录下生成了 3 个 html 文件,分别是 index.html 、 page1.html 和 page2.html

四、使用 pages 配置

其实,在 vue.config.js 中,我们还有一个配置没有使用,便是 pages 。 pages 对象允许我们为应用配置多个入口及模板,这就为我们的多页应用提供了开放的配置入口。官方示例代码如下

/* vue.config.js */
module.exports = {
 pages: {
  index: {
   // page 的入口
   entry: 'src/index/main.js',
   // 模板来源
   template: 'public/index.html',
   // 在 dist/index.html 的输出
   filename: 'index.html',
   // 当使用 title 选项时,
   // template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
   title: 'Index Page',
   // 在这个页面中包含的块,默认情况下会包含
   // 提取出来的通用 chunk 和 vendor chunk。
   chunks: ['chunk-vendors', 'chunk-common', 'index']
  },
  // 当使用只有入口的字符串格式时,
  // 模板会被推导为 `public/subpage.html`
  // 并且如果找不到的话,就回退到 `public/index.html`。
  // 输出文件名会被推导为 `subpage.html`。
  subpage: 'src/subpage/main.js'
 }
}

我们不难发现, pages 对象中的 key 就是入口的别名,而其 value 对象其实是入口 entry 和模板属性的合并,这样我们上述介绍的获取多入口和多模板的方法就可以合并成一个函数来进行多页的处理,合并后的 setPages 方法如下

// pages 多入口配置
exports.setPages = configs => {
 let entryFiles = glob.sync(PAGE_PATH + '/*/*.js')
 let map = {}

 entryFiles.forEach(filePath => {
  let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
  let tmp = filePath.substring(0, filePath.lastIndexOf('\/'))

  let conf = {
   // page 的入口
   entry: filePath, 
   // 模板来源
   template: tmp + '.html', 
   // 在 dist/index.html 的输出
   filename: filename + '.html', 
   // 页面模板需要加对应的js脚本,如果不加这行则每个页面都会引入所有的js脚本
   chunks: ['manifest', 'vendor', filename], 
   inject: true,
  };

  if (configs) {
   conf = merge(conf, configs)
  }

  if (process.env.NODE_ENV === 'production') {
   conf = merge(conf, {
    minify: {
     removeComments: true, // 删除 html 中的注释代码
     collapseWhitespace: true, // 删除 html 中的空白符
     // removeAttributeQuotes: true // 删除 html 元素中属性的引号
    },
    chunksSortMode: 'manual'// 按 manual 的顺序引入
   })
  }

  map[filename] = conf
 })

 return map
}

上述代码我们 return 出的 map 对象就是 pages 所需要的配置项结构,我们只需在 vue.config.js 中引用即可

/* vue.config.js */

const utils = require('./build/utils')

module.exports = {
 ...
 
 pages: utils.setPages(),
 
 ...
}

这样我们多页应用基于 pages 配置的改进就大功告成了,当你运行打包命令来查看输出结果的时候,你会发现和之前的方式相比并没有什么变化,这就说明这两种方式都适用于多页的构建,但是这里还是推荐大家使用更便捷的 pages 配置

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
js弹窗代码 可以指定弹出间隔
Jul 03 Javascript
简单实用的js调试logger组件实现代码
Nov 20 Javascript
js css后面所带参数含义介绍
Aug 18 Javascript
JS window对象的top、parent、opener含义介绍
Dec 03 Javascript
jquery原创弹出层折叠效果点击折叠弹出一个层
Mar 12 Javascript
javascript设计模式之中介者模式Mediator
Dec 30 Javascript
Javascript中的方法和匿名方法实例详解
Jun 13 Javascript
全面解析JavaScript里的循环方法之forEach,for-in,for-of
Apr 20 Javascript
值得分享的JavaScript实现图片轮播组件
Nov 21 Javascript
jQuery实现手机号正则验证输入及自动填充空格功能
Jan 02 jQuery
在小程序中使用Echart图表的示例代码
Aug 02 Javascript
微信小程序版本自动更新的方法
Jun 14 Javascript
Vue基础学习之项目整合及优化
Jun 02 #Javascript
JavaScript判断对象和数组的两种方法
May 31 #Javascript
vue中node_modules中第三方模块的修改使用详解
May 31 #Javascript
Vuex新手的理解与使用详解
May 31 #Javascript
一文快速了解JQuery中的AJAX
May 31 #jQuery
gulp构建小程序的方法步骤
May 31 #Javascript
jQuery实现动态加载(按需加载)javascript文件的方法分析
May 31 #jQuery
You might like
用PHP制作的意见反馈表源码
2007/03/11 PHP
php学习之变量的使用
2011/05/29 PHP
destoon之一键登录设置
2014/06/21 PHP
TP框架实现上传一张图片和批量上传图片的方法分析
2020/04/23 PHP
javascript下有关dom以及xml节点访问兼容问题
2007/11/26 Javascript
在IE上直接编辑网页内容的js代码(IE地址栏js)
2009/04/27 Javascript
jQuery 行级解析读取XML文件(附源码)
2009/10/12 Javascript
jQuery切换所有复选框选中状态的方法
2015/07/02 Javascript
BootStrap智能表单实战系列(七)验证的支持
2016/06/13 Javascript
BootStrapValidator校验方式
2016/12/19 Javascript
详解从零搭建 vue2 vue-router2 webpack3 工程
2017/11/22 Javascript
vue2中使用less简易教程
2018/03/27 Javascript
vue中$set的使用(结合在实际应用中遇到的坑)
2018/07/10 Javascript
vue-cli3项目打包后自动化部署到服务器的方法
2020/09/16 Javascript
JavaScript 实现轮播图特效的示例
2020/11/05 Javascript
vue created钩子函数与mounted钩子函数的用法区别
2020/11/05 Javascript
Vue 3.0中jsx语法的使用
2020/11/13 Javascript
[44:40]KG vs LGD 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
Python打包可执行文件的方法详解
2016/09/19 Python
在Django同1个页面中的多表单处理详解
2017/01/25 Python
Python实现的下载网页源码功能示例
2017/06/13 Python
简单了解python字符串前面加r,u的含义
2019/12/26 Python
使用OpenCV circle函数图像上画圆的示例代码
2019/12/27 Python
基于python爬取梨视频实现过程解析
2020/11/09 Python
通过css3动画和opacity透明度实现呼吸灯效果
2019/08/09 HTML / CSS
HTML5的结构和语义(2):结构
2008/10/17 HTML / CSS
泰国办公用品购物网站:OfficeMate
2018/02/04 全球购物
美国市场上最实惠的送餐服务:Dinnerly
2018/03/18 全球购物
公司授权委托书格式样本
2014/10/01 职场文书
领导干部个人整改措施落实情况汇报
2014/10/29 职场文书
2015年五一劳动节活动总结
2015/02/09 职场文书
2015年公司行政后勤工作总结
2015/05/20 职场文书
公司开业主持词
2015/07/02 职场文书
SpringBoot生成License的实现示例
2021/06/16 Java/Android
Python+Selenium自动化环境搭建与操作基础详解
2022/03/13 Python
解决xampp安装后Apache无法启动
2022/03/21 Servers