vue单页到多页的配置

前言

vue如果改成多页,可以减少每次渲染的包大小,每个页面也可以成为一个新的单页,可以更合理划分业务内容。分别写了html及pug两个模板引擎的多页模板,仓库地址如下:

  • vue多页项目模板,基于html模板
  • vue多页项目模板,基于pug模板引擎

vue单页改成多页步骤

  • 此步骤是基于上一篇vue单页项目模板搭建的,并且使用的是html模板,有不清楚的webpack配置可以去该仓库查询
  • 修改目录结构:将app目录下的pages下的页面结构修改成如下,文件夹名-js文件名-html文件名需要一致,且定义的页面路由开头也需要与文件名一致,页面内容不详讲。
    .
    ├── README.md
    ├── app // 前端目录
    │   ├── assets
    │   │   ├── images
    │   │   ├── js
    │   │   └── less
    │   ├── components
    │   └── pages
    │       ├── home
    │       │   ├── detail.vue
    │       │   ├── home.html
    │       │   ├── home.js
    │       │   └── main.vue
    │       └── user
    │           ├── main.vue
    │           ├── user.html
    │           └── user.js
    ├── back-end  // 后端服务
    ├── build  // webpack配置
    │   ├── build.js
    │   ├── utils.js
    │   ├── webpack.common.conf.js
    │   ├── webpack.dev.conf.js
    │   └── webpack.prod.conf.js
    ├── dist // 打包文件
    ├── package.json
    ├── test
    ├── webpack.config.js
    
  • 修改webpack配置
    • 修改入口配置

      // 新建文件 utils.js
      const path = require('path')
      // `glob`: 匹配文件, 该模块允许你使用 * 等符号, 例如lib/*.js就是获取lib文件夹下的所有js后缀名的文件
      const glob = require('glob')
      const PAGE_PATH = path.resolve(__dirname, '../app/pages')
      
      //多入口配置:通过js文件名
      exports.entries = function () {
        // 通过glob模块读取pages文件夹下的所有对应文件夹下的js后缀文件
        var entryFiles = glob.sync(PAGE_PATH + '/*/*.js')
        var map = {}
        entryFiles.forEach((filePath) => {
          // 获取文件名
          var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
          map[filename] = filePath
        })
        return map
      }
      

      修改入口:

        entry: utils.entries(),
      
    • 修改html生成配置

      • webpack.dev.conf.js:注释掉原来定义的HtmlWebpackPlugin,并改成下面的
        plugins: [
          // new HtmlWebpackPlugin({
          //   filename: 'index.html',
          //   title: '',
          //   template: path.join(appDir, 'index.html'),
          //   inject: true,
          //   chunks: ['app']
          // })
        ],
        
        const glob = require('glob')
        const PAGE_PATH = path.resolve(__dirname, '../app/pages')
        
        let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')
        entryHtml.forEach((filePath) => {
          let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
          let conf = {
            filename: filename + '.html',
            template: filePath,
            inject: true,
            chunks: [filename], // 页面模板需要加对应的js脚本,如果不加这行则每个页面都会引入所有的js脚本
          }
          config.plugins.push(new HtmlWebpackPlugin(conf))
        })
        
      • webpack.prod.conf.js:注释掉原来定义的HtmlWebpackPlugin,并改成下面的
       plugins: [
         // new HtmlWebpackPlugin({
         //   filename: 'index.html', 
         //   template: path.join(appDir, 'index.html'),
         //   title: '',
         //   inject: true,
         //   minify: {
         //     removeComments: true,
         //     collapseWhitespace: true,
         //     removeAttributeQuotes: true,
         //     conservativeCollapse: true
         //   },
         //   chunks: ['manifest', 'vendors', 'app']
         // }),
         new webpack.HashedModuleIdsPlugin(),
         // new InlineManifestWebpackPlugin('manifest') 
       ],
      
      const glob = require('glob')
      const PAGE_PATH = path.resolve(__dirname, '../app/pages')
      
      let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')
      entryHtml.forEach((filePath) => {
        let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
        let conf = {
          filename: filename + '.html', 
          template: filePath,
          minify: {
            removeComments: true,
            collapseWhitespace: true,
            removeAttributeQuotes: true,
            conservativeCollapse: true
          },
          inject: true,
          chunksSortMode: 'dependency',
          chunks: ['manifest', 'vendors', filename],
        }
        config.plugins.push(new HtmlWebpackPlugin(conf))
      })
      // 需放在HtmlWebpackPlugin下面
      config.plugins.push(new InlineManifestWebpackPlugin('manifest'))
      
    • 到这步,已经可以正常执行打包npm run build,但是开发调试的时候npm run dev,发现页面输入的页面路由http://xxxx:9001/home直接404了,解决办法是,需要在devServer中配置重写操作指定页面,不然都是直接默认查找index.html页面的。

        // utils.js
        exports.rewrites = function () {
          const entries = exports.entries();
          const rewrites = [];
          Object.keys(entries).forEach((name) => {
            const reg = new RegExp(`^\/${name}`);
            rewrites.push({ from: reg, to: `\/${name}.html` });
          });
          console.log(rewrites);
          return rewrites;
        };
      
      // webpack.dev.conf.js
      devServer: {
       ...
        historyApiFallback: {
          rewrites: utils.rewrites() // 重要!路由匹配html页面,不配置则通过路由找不到页面
        }, 
        ...
      },
      
      

      配置完后就可以正常按照路由打开页面了。

    • 由于vue-router我使用了history模式的路由,打包后的页面需要在服务器端配置路由,通过后端render才可打开页面(或者你可以采用hash模式的路由,就可以直接打开html页面),我写了一个back-end的简单服务器端,到目录下执行npm run dev,,打开http://localhost:3000/home即可看到对应打包页面内容。因为,上线前,需要后端配置前端的页面路由指定的html页面。

使用pug模板引擎

  • 安装依赖
    npm install -save-dev pug pug-loader
    
  • 修改webpack配置
    • webpack.common.conf.js,增加pug-loader
      module: {
        rules: [
          ...
          {
            test: /\.pug$/,
            loader: 'pug-loader'
          },
        ]
      },
      
    • webpack.dev.conf.js & webpack.prod.conf.js,修改入口文件后缀
      - let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')
      + let entryHtml = glob.sync(PAGE_PATH + '/*/*.pug')
      
  • 修改页面模板
    .
    ├── README.md
    ├── app // 前端目录
         ├── assets
         │   ├── images
         │   ├── js
         │   ├── layout
         │   │     └── base.pug // 新增公共pug
         │   └── less
         ├── components
         └── pages
             ├── home
             │   ├── detail.vue
             │   ├── home.pug  // 修改文件后缀及内容
             │   ├── home.js
             │   └── main.vue
             └── user
                 ├── main.vue
                 ├── user.pug  // 修改文件后缀及内容
                 └── user.js
    
    

参考文章

  • vue构建多页面应用实例代码分享
  • 用vue构建多页面应用
  • pug

你可能感兴趣的:(vue单页到多页的配置)