webpack从0到1 - 下

226 阅读4分钟

前言

大家好,我是Frank。今天我们接上一篇文章继续来说一下webpack中一些扩展配置。

正文

5.Plugins:webpack的扩展补充

  • 作用于webpack打包整个过程
  • webpack的打包过程是有(生命周期概念)钩子

plugin 可以在webpack运行到某个阶段的时候,帮你做一些事情,类似于生命周期的概念

扩展插件,在 Webpack 构建流程中的特定时机注入扩展逻辑来改变构建结果或做你想要的事情。

作用于整个构建过程

HtmlWebpackPlugin

​ htmlwebpackplugin会在打包结束后,自动生成一个html文件,并把打包生成的js模块引入到该html中。

npm install --save-dev html-webpack-plugin

配置:

字段 作用
title 用来生成页面的 title 元素
filename 输出的 HTML 文件名,默认是 index.html, 也可以直接配置带有子目录。
template 模板文件路径,支持加载器,比如 html!./index.html
inject true|'head'|'body'|false ,注入所有的资源到特定的 template 或者 templateContent 中,如果设置为 true 或者 body,所有的 javascript 资源将被放置到 body 元素的底部,'head' 将放置到 head 元素中。
favicon 添加特定的 favicon 路径到输出的 HTML 文件中。
minify {} | false , 传递 html-minifier 选项给 minify 输出
hash true | false, 如果为 true, 将添加一个唯一的 webpack 编译 hash 到所有包含的脚本和 CSS 文件,对于解除 cache 很有用。
cache true | false,如果为 true, 这是默认值,仅仅在文件修改之后才会发布文件。
showErrors true | false, 如果为 true, 这是默认值,错误信息会写入到 HTML 页面中
chunks 允许只添加某些块 (比如,仅仅 unit test 块)
chunksSortMode 允许控制块在添加到页面之前的排序方式,支持的值:'none' | 'default' | {function}-default:'auto'
excludeChunks 允许跳过某些块,(比如,跳过单元测试的块)

案例:

const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
 ...
  plugins: [
    new htmlWebpackPlugin({
      title: "My App",
      filename: "app.html",
      template: "./src/index.html"
    })
  ]
};
//index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

clean-webpack-plugin

npm install --save-dev clean-webpack-plugin
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

...

plugins: [
    new CleanWebpackPlugin()
]

clean-webpack-plugin:如何做到dist目录下某个文件或目录不被清空: 使用配置项:cleanOnceBeforeBuildPatterns 案例:cleanOnceBeforeBuildPatterns: ["/*", "!dll", "!dll/"], !感叹号相当于exclude 排除,意思是清空操作排除dll目录,和dll目录下所有文件。 注意:数组列表里的“**/*”是默认值,不可忽略,否则不做清空操作。

6.WebpackDevServer

  • 提升开发效率的利器

每次改完代码都需要重新打包一次,打开浏览器,刷新一次,很麻烦,我们可以安装使用webpackdevserver来改善这块的体验

  • 安装
 npm install webpack-dev-server@3.11.0 -D 
  • 配置

修改下package.json

"scripts": {
    "server": "webpack-dev-server"
  },

在webpack.config.js配置:

devServer: {
    contentBase: "./dist",
    open: true,
    port: 8081
  },
  • 启动
npm run server

启动服务后,会发现dist目录没有了,这是因为devServer把打包后的模块不会放在dist目录下,而是放到内存中,从而提升速度

7.HotModuleReplacement(热模块替换)

  • css模块HMR JS模块HMR

  • 不支持抽离出的css 我们要使用css-loader

启动hmr

devServer: {
    contentBase: "./dist",
    open: true,
    hot:true,
    // hotOnly:true
    // only和hotOnly在某些模块不支持热更新的情况下,前者会自动刷新页面,后者不会刷新页面,而是在控制台输出热更新失败
  },

配置文件头部引入webpack

//const path = require("path");
//const HtmlWebpackPlugin = require("html-webpack-plugin");
//const CleanWebpackPlugin = require("clean-webpack-plugin");

const webpack = require("webpack");

在插件配置处添加:

plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: "src/index.html"
    }),
    new webpack.HotModuleReplacementPlugin()
  ],

案例:处理css模块HMR

//index.js
import "./css/index.css";

var btn = document.createElement("button");
btn.innerHTML = "新增";
document.body.appendChild(btn);

btn.onclick = function() {
  var div = document.createElement("div");
  div.innerHTML = "item";
  document.body.appendChild(div);
};


//index.css
div:nth-of-type(odd) {
  background: yellow;
}

注意启动HMR后,css抽离会不生效,还有不支持contenthash,chunkhash

处理js模块HMR

​ 需要使用module.hot.accept来观察模块更新 从而更新

案例:

//counter.js
function counter() {
  var div = document.createElement("div");
  div.setAttribute("id", "counter");
  div.innerHTML = 1;
  div.onclick = function() {
    div.innerHTML = parseInt(div.innerHTML, 10) + 1;
  };
  document.body.appendChild(div);
}
export default counter;


//number.js
function number() {
  var div = document.createElement("div");
  div.setAttribute("id", "number");
  div.innerHTML = 13000;
  document.body.appendChild(div);
}
export default number;




//index.js

import counter from "./counter";
import number from "./number";

counter();
number();

if (module.hot) {
  module.hot.accept("./b", function() {
    document.body.removeChild(document.getElementById("number"));
    number();
  });
}

后记

好了,本次webpack的分享到这里就结束了,感谢大家的阅读,下期再见~

本文使用 mdnice 排版