交流群:462197261站长百科站长论坛热门标签收藏本站北冥有鱼 互联网前沿资源第一站 助力全行业互联网+
点击这里给我发消息
  • 当前位置:
  • Vue CLI3基础学习之pages构建多页应用

    前言

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

    既然多页应用拥有多个 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
    }

    读取并存储完毕后,我们得到了一个入口文件的对象集合,这个对象我们便可以将其设置到 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
    }

    • 以上我们仍然是使用 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 配置

    总结

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

    您可能感兴趣的文章:

    • vue cli 3.x 项目部署到 github pages的方法
    • Vue-cli创建项目从单页面到多页面的方法
    • 详解vue-cli + webpack 多页面实例配置优化方法
    • vue-cli实现多页面多路由的示例代码
    • 详解如何将 Vue-cli 改造成支持多页面的 history 模式
    • 详解vue-cli + webpack 多页面实例应用
    • vue-cli创建的项目,配置多页面的实现方法
    • 基于vue cli重构多页面脚手架过程详解
    • 详解vue-cli多页面工程实践

    广而告之:
    热门推荐:
    JS面向对象编程浅析

    在AJAX兴起以前,很多人写JS可以说都是毫无章法可言的,基本上是想到什么就写什么,就是一个接一个的函数function,遇到重复的还得copy,如果一不小心函数重名了,还真不知道从何开始查找错误,因为大家总是用面向过程的编程思想来写JS代码,而且也由于网络上充斥了太多···

    BootStrap制作导航条实例代码

    什么是 Bootstrap? Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的。 bootstrap 导航条摸索了好久,要不就是左边和右边不会水平对齐,要不就是颜色不一样,菜鸟最后终于搞定,直接把代码放这里,以后直接用 代码如下···

    php调用云片网接口发送短信的实现方法

    php调用云片网接口发送短信的实现方法 云片网发送短信 /** * [SendSms description] * @param [string] $tpl_content [发送的短信内容] * @param $send_mobile [发送的手机号码] */ public function SendSms($tpl_content,$send_mobile) { $this->···

    简单了解linux终端创建文件的2种常用方法

    我们都知道可以用mkdir命令创建一个新的目录,但更多时候如果能直接创建一个文件(普通文件)会让人感觉更愉悦;这样就可以不用在去打开一个专门的创建文本文件的软件,然后还要设置文件名,保存路径那样的繁琐了;下面就介绍一些关于在linux终端下直接创建文件的方法 方法1 我们···

    ASP.NET中 PlaceHolder 控件的使用方法

    使用 PlaceHolder 控件可以将空容器控件放到网页中,然后在运行时动态添加、删除或遍历各子元素。该控件只呈现其子元素;它本身并没有基于 HTML 的输出。 在实际使用过程中可以向PlaceHolder添加任何Html控件,甚至包括JavaScript代码。 将 PlaceHolder 控件用作存储动态添加到···

    很实用的js选项卡切换效果

    本文实例为大家分享了js实现简单的选项卡切换效果的具体代码,供大家参考,具体内容如下 js选项卡切换代码: <!DOCTYPE html> <html> <head lang="en"> <meta charset="gb2312"> <title>实践题 - 选项卡</title> <style type="···

    一个伴随ASP.NET从1.0到4.0的OutputCache Bug介绍

    我们先来一睹这个Bug的风采! 在一个.aspx文件中增加OutputCache设置,代码如下: 复制代码 代码如下: <%@ OutputCache Duration="300" VaryByParam="*"%> 上面的设置表示:缓存5分钟,根据不同的查询字符串更新缓存。Location使用的是默认值Any,也就是可以在浏···

    html5-Canvas可以在web中绘制各种图形

    在html5中我觉得最重要的就是引入了Canvas,使得我们可以在web中绘制各种图形。给人感觉单在这点上有点模糊我们web和桌面程序的感觉。在html5外web中也有基于xml的绘图如:VML、SVG。而Canvas为基于像素的绘图。Canvas是一个相当于画板的html节点,我们必须以js操作绘图。 如下···

    PHP GD库生成图像的几个函数总结

    使用GD库中提供的函数动态绘制完成图像以后,就需要输出到浏览器或者将图像保存起来。在PHP中,可以将动态绘制完成的画布,直接生成GIF、JPEG、PNG和WBMP四种图像格式。可以通过调用下面四个函数生成这些格式的图像: 复制代码 代码如下:   bool imagegif(resource $image[,s···

    html doctype 作用介绍

    文档模式主要有以下两个作用: 1、告诉浏览器使用什么样的html或xhtml规范来解析html文档 2、对浏览器的渲染模式产生影响;不同的渲染模式会影响到浏览器对于 CSS 代码甚至 JavaScript 脚本的解析,所以Doctype是非常关键的,尤其是在 IE 系列浏览器中,由DOCTYPE 所决···