> 文档中心 > 基于webpack5的多页面打包

基于webpack5的多页面打包

基于webpack5的多页面打包

  • 前言
  • 功能配置篇

前言

在实际开发要求中我们可能无法是使用单页面开发框架(例如vue,react),这些要求主要是基于SEO角度出发(当然可以使用服务端渲染解决,这里我们不考虑),这时候我们就需要进行传统模式的前端开发,传统模式下会有css兼容与压缩,icon图片base64化减少http请求,公共代码引入,js模块化等基础问题。关于wepack多页面打包的资料文档很丰富,实际遇到问题不要惊慌可以去网上查询或者去看看官方文档(webpack文档-传送门)。本篇文章是基于最新版本的webpack来实现多页面打包的,不仅解决了上述基础问题还增加了本地服务,修改自更新,公共代码自动引入等实用功能。本文的webpack打包框架已开源至github欢迎大家的start(git-传送门)

下面我们采用已功能为导向的webpack5多页面打包配置介绍

功能配置篇

1、初始化webpack

npm initnpm 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(),]

9、package.json配置

"scripts": {    "init": "webpack init",    "test": "webpack serve --mode development",    "build": "webpack --mode=production --node-env=production",    "build:dev": "webpack --mode=development",    "build:prod": "webpack --mode=production --node-env=production",    "watch": "webpack --watch",    "serve": "webpack serve --mode development",    "dev": "webpack serve --mode development"  },

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