乐趣区

关于webpack:基于webpack5的多页面打包

前言

在理论开发要求中咱们可能无奈是应用单页面开发框架(例如 vue,react),这些要求次要是基于 SEO 角度登程(当然能够应用服务端渲染解决,这里咱们不思考),这时候咱们就须要进行传统模式的前端开发,传统模式下会有 css 兼容与压缩,icon 图片 base64 化缩小 http 申请,公共代码引入,js 模块化等根底问题。对于 wepack 多页面打包的材料文档很丰盛,理论遇到问题不要惊恐能够去网上查问或者去看看官网文档(webpack 文档 - 传送门)。本篇文章是基于最新版本的 webpack 来实现多页面打包的,不仅解决了上述根底问题还减少了本地服务,批改自更新,公共代码主动引入等实用功能。本文的 webpack 打包框架已开源至 githua 欢送大家的 start(git- 传送门)

上面咱们采纳已性能为导向的 webpack5 多页面打包配置介绍

性能配置篇

1、初始化 webpack

npm init
npm install webpack webpack-cli -g   // -g 更换为 --save-dev 是本地装置
webpack-cli init

2、图片文件及其他文件解决,webpack5 集中到了 asset 模块, 之前应用 file-loader、url-loader、raw-loader 三个

asset/resource 将资源宰割为独自的文件,并导出 url,就是之前的 file-loader 的性能.
asset/inline 将资源导出为 dataURL(url(data:))的模式,之前的 url-loader 的性能.
asset/source 将资源导出为源码(source code). 之前的 raw-loader 性能.
asset 主动抉择导出为独自文件或者 dataURL 模式(默认为 8KB). 之前有 url-loader 设置 asset size limit 限度实现。

配置

webpack.config.js

module: {
    rules: [
      {test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
        type: "asset",
        generator: {
           // 输入文件名
           filename: 'static/[hash][ext][query]'
        }
      }
    ]
}
// 还能够限度解决的大小,这里应用了默认值

3、解决 html 文件,为了后盾敌人好绑定不进行压缩操作,解决 html 里 icon 与资源

webpack.config.js

module: {
    rules: [
      {
        test: /\.html$/,
        loader: 'html-loader',
        options: {
          minimize: false,
          // html 不解决 link\script 标签(为了引入动态资源不 hash)
          sources: {
            list: [
              '...',
              {
                tag: 'script',
                attribute: 'src',
                type: 'src',
                filter : () => false,},
              {
                tag: 'link',
                attribute: 'href',
                type: 'src',
                filter : () => false,}
            ]
          }
        }
      }
    ]
}

4、解决 js、css 进行兼容与压缩

webpack.config.js

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const stylesHandler = MiniCssExtractPlugin.loader;
plugins: [new CssMinimizerPlugin()   // css 压缩
],
module: {
    rules: [
       {test: /\.(js|jsx)$/i,
        loader: "babel-loader",
      },
      {
        test: /\.css$/i,
        use: [stylesHandler, "css-loader", "postcss-loader"],
      }
    ]
}

5、公共代码解决,这里解决的是当多个页面(>=2)有独特引入的话做一次打包引入到多页面,从而节省开支缩小 http 申请。主动引入公共文件会在下边解说。

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
plugins: [
   // 合并文件内 css
   new MiniCssExtractPlugin({filename: 'css/[name]/[name].[hash].css'
   }),
   // 复制动态资源库
   new CopyPlugin({
     patterns: [{ from: path.resolve(__dirname, 'static'), to: 'static' }
     ],
   })
]
optimization: {
    splitChunks: {
      cacheGroups: {
        // 打包公共模块
        commons: {
          //initial 示意提取入口文件的公共局部
          chunks: 'initial',
          // 示意提取公共局部起码的文件数
          minChunks: 2,
          // 示意提取公共局部最小的大小
          minSize: 0,
          // 提取进去的文件命名
          name: 'commons'
        }
      }
    }
}

6、工程化配置入口文件及入口模板

wepack.batch.entry.js(创立)

const path = require('path')
const glob = require('glob')
const HtmlWebpackPlugin = require("html-webpack-plugin");
const publicPath = './'

// 入口文件
const entry = {}
// 入口文件对应的模板
const entryTemplate = []

exports.entry = () => {seekAllFile()
  setEntryTemplate()
  return {entry, entryTemplate}
}

// 失去 pages 文件夹下所有入口文件(反对有限嵌套)
const seekAllFile = (parent = 'pages/*') => {const fileList = glob.sync(path.resolve(__dirname, parent))
  if (fileList.length > 0) {
    fileList.forEach(file => {const regJs = file.match(/.*\/(.*js)/i)
      if (regJs !== null && regJs[1]) {const jsName = regJs[1]
        const key = jsName.match(/(.*).js/i)[1]
        entry[key] = publicPath + parent.replace(/\*/, '') + jsName
      } else {const parentPath = parent.replace(/\*/, '')
        const reg = new RegExp(parentPath + '(.*)', 'i')
        const folder = file.match(reg)[1]
        if (!file.match(/.*\/(.*?)\..*/)) {console.log(file)
          seekAllFile(parentPath + folder + '/*')
        }
      }
    })
  } else {return}
}

// 设置入口文件的模板文件(附加性能)
const setEntryTemplate = () => {Object.keys(entry).forEach(key => {
    entryTemplate.push(new HtmlWebpackPlugin({template: entry[key].replace(/\.js/, '.html'),
      filename: key + '.html',
      chunks: [key],
      inject: 'body',
      minify: false
    }))
  })
}

pages 下的所有文件会被主动设置问入口及入口文件(反对有限嵌套),然而要求构造如下
pages/index/index.js index.html js 文件名与 html 文件名同名且同级
这样入口文件为 js, 模板为 html

webpack.config.js

const batch = require('./wepack.batch.entry')['entry']();

{
  entry: batch.entry,
  plugins: [
    // 入口文件对应的模板
    ...batch.entryTemplate,
  ]
}

7、主动引入公共文件,前提是在根目录创立 automation 文件夹,目录下 index.js 里的引入资源会被引入到个个模板中

webpack.automation.load.js(创立)

// 自动化引入公共文件(如 reset.css)

/**
 * @desc: 主动引入公共文件 - 所有模板
 * @param {Object} batch.entry 入口文件
 * @param {Array} batch.entryTemplate  模板
 */
exports.automation = (batch) => {batch.entry['automations'] = './automation/index.js'
  batch.entryTemplate.forEach(item => {item.userOptions.chunks.unshift('automations')
    item.userOptions.chunksSortMode = 'manual'
  })
}

webpack.config.js

const batch = require('./wepack.batch.entry')['entry']();
const autoLoad = require('./webpack.automation.load')
// 主动引入 automation/index.js 中的内容 - 可自在配置
autoLoad.automation(batch)

automation/index.js

import '../common/css/reset.css'

这样每个入口文件模板就会引入 reset.css,性能外围就是配置 HtmlWebpackPlugin 的 chunks

8、本机服务及批改自更新

webpack.config.js

const {CleanWebpackPlugin} = require('clean-webpack-plugin');
output: {path: path.resolve(__dirname, "dist"),
    filename: 'js/[name]/[name].[hash].js'
},
devServer: {contentBase:  path.resolve(__dirname, "dist"),
    compress: true,
    hot: false,
    open: true,
    port: 8080,
},
plugins: [
  // 革除生成文件夹在 build
  new CleanWebpackPlugin(),]

webpack5 的多页面打包根本配置就如上所述了,对于本文 demo 已开源至 github(git- 传送门),如果您有应用问题请您发问或者 git 上 issues 问题

退出移动版