详解Vue CLI3 多页应用实践和源码设计


Posted in Javascript onAugust 30, 2018

 对于一个网站来说,即需要h5页面也同时需要web页面,而h5和web页面共用很多代码,不做响应式,只能拆分两个页面来写,一个h5,一个web.用vue cli3怎么配置h5与web的应用呢?

解决思路:

首先,需要产生多页面应用,用webpack配置成多页面应用,一个h5一个web,这个网上已经有很多教程了,下面会再整理一次,接着把所有公共的代码提到多页面目录外面.

我们看一下官网给的 multi-page 的配置:需要在 vue.config.js 配置 pages,示例如下:

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'
 }

每一个页面中就是一个对象,包含了如下配置:

  • entry 入口文件的路径
  • template 模板文件的路径
  • filename 编译之后的 html 文件名
  • title html 中的 title
  • chunks 打包的 chunk 文件,数组格式,包含入口文件

首先,我们需要设计一下 src 目录下面放置 multi-page 的文件:

看了很多多页项目,有 2 个方案:

  • 一种叫 pages 文件夹
  • 一种叫 views 或者其他名字的文件夹

大家自行选择或者定义就好了,这里我们选 pages

我们再看一下里面的文件:

  • 入口文件:文件名可以叫 main.js 或者 index.js
  • 模板文件:可以用统一的 'public/index.html',或者目录内放置一个自己的,取名 index.html
  • title:可以从一个文件里面取
src
 pages
 page1
  index.html
  main.js
  App.vue
 page2
  index.html
  main.js
  App.vue

下面就是通过函数来生成 pages 的配置:

第一步:找到入口文件

可以用 glob

const glob = require('glob')

pages 目录的位置,可以用相对路径,也可以用绝对路径:

const path = require('path')
const PAGES_PATH = path.resolve(__dirname, './src/pages')

定义一个 pages 对象:

const pages = {}
glob.sync(PAGES_PATH + '/*/main.js').forEach(filepath => {
 // ...
})

这里就是去设置对应几个 key 了,很多项目基本多是通过

/ 分隔符来对字符串进行数组话,然后简单地获取

但是熟悉 node.js path 模块的会如下处理:

const pageName = path.basename(path.dirname(filepath))

往 pages 里面循环设置:

pages[pageName] = {
 entry: filepath,
 filename: `${pageName}.html`,
 chunks: ['chunk-vendors', 'chunk-common', pageName]
 }

关于 template 稍微复杂一点,我们需要做判断,如果存在就用自定义的,如果不存在就用通用的

const templatePath = path.dirname(filepath) + '/index.html'

然后通过 fs.existsSync 会判断自定义文件是否存在:

if (!fs.existsSync(templatePath)) {
 // 入口如果不配置直接使用
 templatePath = 'public/index.html'
 }

当然后面我们分享了源码之后,你就会发现你做了无用功

下面我们看一下源码实现部分:

每个版本的 cli-service 多有微小的改动

cli-service/lib/config/app.js 文件

定义了一个变量 multiPageConfig 获取 vue.config.js 取出来的 pages:

const multiPageConfig = options.pages

清空一次 entry

webpackConfig.entryPoints.clear()

通过 Object.keys 获取 keys,然后 forEach 循环

const pages = Object.keys(multiPageConfig)
pages.forEach(name => {
})

循环内部:

先定义要用的变量,从 multiPageConfig[name] 的每一个对象取:

const {
   title,
   entry,
   template = `public/${name}.html`,
   filename = `${name}.html`,
   chunks
  } = normalizePageConfig(multiPageConfig[name])

normalizePageConfig 函数如下:

处理 subpage: 'src/subpage/main.js' 的情况

const normalizePageConfig = c => typeof c === 'string' ? { entry: c } : c

设置 entry

webpackConfig.entry(name).add(api.resolve(entry))

hasDedicatedTemplate 是判断

用户传递的多页配置自定义模板路径是否存在:

const fs = require('fs')
const hasDedicatedTemplate = fs.existsSync(api.resolve(template))

templatePath 的处理细节:

htmlPath 路径是:

/Users/*/public/index.html

const htmlPath = api.resolve('public/index.html')

defaultHtmlPath 路径是:

/Users/*/node_modules/@vue/cli-service/lib/config/index-default.html

const defaultHtmlPath = path.resolve(__dirname, 'index-default.html')

如果:

1、用户自定义的模板存在就直接给 templatePath
2、如果不存在,先取 public/index.html,再不行就取 node_modules 里面的

const templatePath = hasDedicatedTemplate
   ? template
   : fs.existsSync(htmlPath)
   ? htmlPath
   : defaultHtmlPath

最终通过 html-webpack-plugin 插件来生成指定名字的 html 文件到指定目录:

1、指定目录:

由 vue.config.js 中的 outputDir 来决定

const outputDir = api.resolve(options.outputDir)

2、生成 webpack config 关于 html-webpack-plugin 的部分:

const HTMLPlugin = require('html-webpack-plugin')
webpackConfig
   .plugin(`html-${name}`)
   .use(HTMLPlugin, [pageHtmlOptions])

pageHtmlOptions 的处理细节:

传递给 html-webpack-plugin 插件的参数,这里默认会设置 chunks 的,所以上面实战中配置也是无用功

const pageHtmlOptions = Object.assign({}, htmlOptions, {
   chunks: chunks || ['chunk-vendors', 'chunk-common', name],
   template: templatePath,
   filename: ensureRelative(outputDir, filename),
   title
  })

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript与css3动画结合使用小结
Mar 11 Javascript
jQuery插件multiScroll实现全屏鼠标滚动切换页面特效
Apr 12 Javascript
js实现简单锁屏功能实例
May 27 Javascript
JQuery实现超链接鼠标提示效果的方法
Jun 10 Javascript
jquery对象和DOM对象的相互转换详解
Oct 18 Javascript
jquery延迟对象解析
Oct 26 Javascript
jQuery 如何实现一个滑动按钮开关
Dec 01 Javascript
EasyUI Datebox 日期验证之开始日期小于结束时间
May 19 Javascript
Javascript中的getter和setter初识
Aug 17 Javascript
微信小程序中使用自定义图标(阿里icon)的方法
Aug 20 Javascript
基于vue开发微信小程序mpvue-docs跳转页面功能
Apr 10 Javascript
JS正则表达式常见函数与用法小结
Apr 13 Javascript
小程序图片长按识别功能的实现方法
Aug 30 #Javascript
解决vue中监听input只能输入数字及英文或者其他情况的问题
Aug 30 #Javascript
解决Js先触发失去焦点事件再执行点击事件的问题
Aug 30 #Javascript
微信小程序之判断页面滚动方向的示例代码
Aug 30 #Javascript
解决vue js IOS H5focus无法自动弹出键盘的问题
Aug 30 #Javascript
在Vue methods中调用filters里的过滤器实例
Aug 30 #Javascript
vue 根据数组中某一项的值进行排序的方法
Aug 30 #Javascript
You might like
整合了前面的PHP数据库连接类~~做成一个分页类!
2006/11/25 PHP
PHP4与PHP5的时间格式问题
2008/02/17 PHP
浅谈web上存漏洞及原理分析、防范方法(安全文件上存方法)
2013/06/29 PHP
php教程之phpize使用方法
2014/02/12 PHP
php模仿qq空间或朋友圈发布动态、评论动态、回复评论、删除动态或评论的功能(中)
2017/06/11 PHP
ASP.NET jQuery 实例18 通过使用jQuery validation插件校验DropDownList
2012/02/03 Javascript
javascript弹出窗口实现代码
2015/11/12 Javascript
jquery+json实现数据二级联动的方法
2015/11/28 Javascript
jquery ezUI 双击行记录弹窗查看明细的实现方法
2016/06/01 Javascript
layer弹出层 iframe层去掉滚动条的实例代码
2018/08/17 Javascript
详解如何使用webpack打包多页jquery项目
2019/02/01 jQuery
vue.js中导出Excel表格的案例分析
2019/06/11 Javascript
关于vue3.0中的this.$router.replace({ path: '/'})刷新无效果问题
2020/01/16 Javascript
[04:55]完美世界副总裁蔡玮:DOTA2的自由、公平与信任
2013/12/18 DOTA
Python制作简单的网页爬虫
2015/11/22 Python
使用Python向C语言的链接库传递数组、结构体、指针类型的数据
2019/01/29 Python
Python字符串逆序的实现方法【一题多解】
2019/02/18 Python
python爬取微信公众号文章的方法
2019/02/26 Python
Python绘制频率分布直方图的示例
2019/07/08 Python
使用Python轻松完成垃圾分类(基于图像识别)
2019/07/09 Python
python基于Selenium的web自动化框架
2019/07/14 Python
基于Python中的yield表达式介绍
2019/11/19 Python
使用TensorFlow对图像进行随机旋转的实现示例
2020/01/20 Python
python中逻辑与或(and、or)和按位与或异或(&amp;、|、^)区别
2020/08/05 Python
在HTML5中如何使用CSS建立不可选的文字
2014/10/17 HTML / CSS
英国HYPE双肩包官网:英国本土时尚潮牌
2018/09/26 全球购物
土耳其风格手工珠宝:Ottoman Hands
2019/07/26 全球购物
Marc O’Polo俄罗斯官方在线商店:德国高端时尚品牌
2019/12/26 全球购物
Agoda中文官网:安可达(低价预订全球酒店)
2021/01/18 全球购物
酒店总经理职务说明书
2014/02/26 职场文书
设备收款委托书范本
2014/10/02 职场文书
2014年助理政工师工作总结
2014/12/19 职场文书
2016大一新生军训心得体会
2016/01/11 职场文书
Python turtle实现贪吃蛇游戏
2021/06/18 Python
Python django中如何使用restful框架
2021/06/23 Python
关于 Python json中load和loads区别
2021/11/07 Python