1
在实际项目中,每次对项目打包后我们都需要手动在index.html添加js,当打包后的js入口文件名更改时,我们又需要再一次修改index.html中的js,有没有觉得很麻烦,现在有一个插件来帮助我们,打包完之后自动生成HTML文件,并自动引入打包后的js文件。

1、安装依赖

npm i html-webpack-plugin html-loader --save-dev

package.json如下:

{
  "name": "webpack_test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack --mode development",
    "build": "webpack --mode production"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.6.4",
    "@babel/plugin-transform-runtime": "^7.6.2",
    "@babel/polyfill": "^7.6.0",
    "@babel/preset-env": "^7.6.3",
    "@babel/runtime": "^7.6.3",
    "babel-loader": "^8.0.6",
    "clean-webpack-plugin": "^3.0.0",
    "core-js": "^3.3.2",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "jquery": "^3.4.1",
    "lodash": "^4.17.15",
    "react": "^16.10.2",
    "webpack": "^4.41.2",
    "webpack-bundle-analyzer": "^3.6.0",
    "webpack-cli": "^3.3.9"
  }
}

解释一下html-webpack-pluginhtml-loader的作用:

html-webpack-plugin插件用于根据配置自动生成html文件,并将打包后的js入口文件自动引入到生成的html中。如果有多个入口文件,它们都会被引入到html中。如果在webpack输出中含有任何的css文件(例如,用mini-css-extract-plugin提取的css),这些文件将包含在html头中的<link>标签中。
参考:https://github.com/jantimon/html-webpack-plugin

html-loader加载器用于html-webpack-plugin在根据html模板生成html时加载html模板。
参考:https://github.com/webpack-contrib/html-loader

html-webpack-pluginhtml-loader之间没有任何依赖关系

2、配置webpack.config.js

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: {
    main: './lazyloading/index.js'
  },
  output: {
    path: path.resolve(__dirname, 'build'), // 打包文件的输出目录
    filename: '[name].bundle.js', // 代码打包后的文件名
    publicPath: __dirname + '/build/', // 引用的路径或者 CDN 地址
    chunkFilename: '[name].js' // 代码拆分后的文件名
  },
  module: {
    rules: [{
      test: /\.html$/,
      use: [{
        loader: 'html-loader'
      }]
    }]
  },
  // 拆分代码配置项
  optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 30000,
      maxSize: 0,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        common: {
          name: 'common',
          minSize: 0, //表示在压缩前的最小模块大小,默认值是 30kb,如果没设置为0,common模块就不会抽离为公共模块,因为原始大小小于30kb
          minChunks: 2, // 最小公用次数
          priority: 5, // 优先级
          reuseExistingChunk: true // 公共模块必开启
        },
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  },
  plugins: [
    new CleanWebpackPlugin(), // 会删除上次构建的文件,然后重新构建
    new BundleAnalyzerPlugin(),
    new HtmlWebpackPlugin({
      // 打包输出HTML
      title: '自动生成 HTML',
      minify: {
        // 压缩 HTML 文件
        removeComments: true, // 移除 HTML 中的注释
        collapseWhitespace: true, // 删除空白符与换行符
        minifyCSS: true // 压缩内联 css
      },
      filename: 'index.html', // 生成后的文件名
      template: path.resolve(__dirname, 'index.html'), // 根据此模版生成 HTML 文件
      chunks: ['main'] // entry中的 main 入口才会被打包
    })
  ]
}

主要是在配置中引入html-loader加载器和html-webpack-plugin插件。

由于使用了 title 选项,则需要在 template 选项对应的 html title 中加入 <%= htmlWebpackPlugin.options.title %>

1.png

3、打包并测试

运行cnpm run build
4.png

5.png

3.png

打包后生成了index.html文件,打开index.html文件发现title部分并没有根据配置改变,这是为什么呢?

原因是因为HtmlWebpackPlugin支持html以及ejs模板语法,当在webpack中配置了html-loader后,就相当于全局设置以html模板语法进行解析,HtmlWebpackPlugin解析html模板是以string类型进行解析,而解析ejs模板是以函数类型进行解析,在全局设置了html-loader后,HtmlWebpackPlugin就不会认识ejs语法了,只会将它当成string直接输出。
参考:
https://blog.csdn.net/kai_vin/article/details/88722662
https://segmentfault.com/q/1010000004555431

现在有两种解决方法:

  • 注释掉配置中添加的html-loaderHtmlWebpackPlugin会默认采用函数类型去解析模板。
  • html模板改成ejs模板。

第一种方式:
注释掉以下代码

  // module: {
  //   rules: [{
  //     test: /\.html$/,
  //     use: [{
  //       loader: 'html-loader'
  //     }]
  //   }]
  // },

打包执行:
6.png

第二种方式:
7.png

8.png

6.png

细心的朋友可能还会发现引入js入口文件的地址是一个绝对地址,但是真实项目需要部署到服务器,使用绝对地址肯定不行的,因为服务器是不可能找得到电脑本地的文件。

所以,我们要将引入的绝对路径改成相对路径,修改publicPath即可,该字段表示引用的路径

修改webpack.config.js

output: {
    path: path.resolve(__dirname, 'build'), // 打包文件的输出目录
    filename: '[name].bundle.js', // 代码打包后的文件名
    publicPath: __dirname + '/build/', // 引用的路径或者 CDN 地址
    chunkFilename: '[name].js' // 代码拆分后的文件名
  },

改成:

output: {
    path: path.resolve(__dirname, 'build'), // 打包文件的输出目录
    filename: '[name].bundle.js', // 代码打包后的文件名
    publicPath: './', // 引用的路径或者 CDN 地址
    chunkFilename: '[name].js' // 代码拆分后的文件名
  },

9.png


记得要微笑
1.9k 声望4.5k 粉丝

知不足而奋进,望远山而前行,卯足劲,不减热爱。


引用和评论

0 条评论