4W字长文带你深度解锁Webpack系列(基础篇)

三篇长文,4W余字,带你解锁 webpack ,但愿读完这三篇文章,你可以对 webpack 的各项配置有一个更为清晰的认识。javascript

1.webpack 是什么?

webpack 是一个现代 JavaScript 应用程序的静态模块打包器,当 webpack 处理应用程序时,会递归构建一个依赖关系图,其中包含应用程序须要的每一个模块,而后将这些模块打包成一个或多个 bundlecss

2.webpack 的核心概念

  • entry: 入口
  • output: 输出
  • loader: 模块转换器,用于把模块原内容按照需求转换成新内容
  • 插件(plugins): 扩展插件,在webpack构建流程中的特定时机注入扩展逻辑来改变构建结果或作你想要作的事情

3.初始化项目

新建一个文件夹,如: webpack-first (固然,你可使用任意一个你喜欢的项目名)。推荐你们参考本文一步一步进行配置,不要老是在网上找什么最佳配置,你掌握了webpack以后,根据本身的需求配置出来的,就是最佳配置。html

本篇文章对应的项目地址(编写本文时使用): https://github.com/YvetteLau/... 前端

使用 npm init -y 进行初始化(也可使用 yarn)。java

要使用 webpack,那么必然须要安装 webpackwebpack-cli:node

npm install webpack webpack-cli -D

鉴于前端技术变动迅速,祭出本篇文章基于 webpack 的版本号:react

├── webpack@4.41.5 
└── webpack-cli@3.3.10

wepack V4.0.0 开始, webpack 是开箱即用的,在不引入任何配置文件的状况下就可使用。webpack

新建 src/index.js 文件,咱们在文件中随便写点什么:git

//index.js
class Animal {
    constructor(name) {
        this.name = name;
    }
    getName() {
        return this.name;
    }
}

const dog = new Animal('dog');

使用 npx webpack --mode=development 进行构建,默认是 production 模式,咱们为了更清楚得查看打包后的代码,使用 development 模式。github

能够看到项目下多了个 dist 目录,里面有一个打包出来的文件 main.js

webpack 有默认的配置,如默认的入口文件是 ./src,默认打包到dist/main.js。更多的默认配置能够查看: node_modules/webpack/lib/WebpackOptionsDefaulter.js

查看 dist/main.js 文件,能够看到,src/index.js 并无被转义为低版本的代码,这显然不是咱们想要的。

{
    "./src/index.js":
        (function (module, exports) {

            eval("class Animal {\n    constructor(name) {\n        this.name = name;\n    }\n    getName() {\n        return this.name;\n    }\n}\n\nconst dog = new Animal('dog');\n\n//# sourceURL=webpack:///./src/index.js?");

        })
}

4.将JS转义为低版本

前面咱们说了 webpack 的四个核心概念,其中之一就是 loaderloader 用于对源代码进行转换,这正是咱们如今所须要的。

将JS代码向低版本转换,咱们须要使用 babel-loader

babel-loader

首先安装一下 babel-loader

npm install babel-loader -D

此外,咱们还须要配置 babel,为此咱们安装一下如下依赖:

npm install @babel/core @babel/preset-env @babel/plugin-transform-runtime -D

npm install @babel/runtime @babel/runtime-corejs3

对babel7配置不熟悉的小伙伴,能够阅读一下这篇文章: 不可错过的 Babel7 知识

新建 webpack.config.js,以下:

//webpack.config.js
module.exports = {
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                use: ['babel-loader'],
                exclude: /node_modules/ //排除 node_modules 目录
            }
        ]
    }
}

建议给 loader 指定 include 或是 exclude,指定其中一个便可,由于 node_modules 目录一般不须要咱们去编译,排除后,有效提高编译效率。

这里,咱们能够在 .babelrc 中编写 babel 的配置,也能够在 webpack.config.js 中进行配置。

建立一个 .babelrc

配置以下:

{
    "presets": ["@babel/preset-env"],
    "plugins": [
        [
            "@babel/plugin-transform-runtime",
            {
                "corejs": 3
            }
        ]
    ]
}

如今,咱们从新执行 npx webpack --mode=development,查看 dist/main.js,会发现已经被编译成了低版本的JS代码。

在webpack中配置 babel

//webpack.config.js
module.exports = {
    // mode: 'development',
    module: {
        rules: [
            {
                test: /\.jsx?$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ["@babel/preset-env"],
                        plugins: [
                            [
                                "@babel/plugin-transform-runtime",
                                {
                                    "corejs": 3
                                }
                            ]
                        ]
                    }
                },
                exclude: /node_modules/
            }
        ]
    }
}

这里有几点须要说明:

  • loader 须要配置在 module.rules 中,rules 是一个数组。
  • loader 的格式为:
{
    test: /\.jsx?$/,//匹配规则
    use: 'babel-loader'
}

或者也能够像下面这样:

//适用于只有一个 loader 的状况
{
    test: /\.jsx?$/,
    loader: 'babel-loader',
    options: {
        //...
    }
}

test 字段是匹配规则,针对符合规则的文件进行处理。

use 字段有几种写法

  • 能够是一个字符串,例如上面的 use: 'babel-loader'
  • use 字段能够是一个数组,例如处理CSS文件是,use: ['style-loader', 'css-loader']
  • use 数组的每一项既能够是字符串也能够是一个对象,当咱们须要在webpack 的配置文件中对 loader 进行配置,就须要将其编写为一个对象,而且在此对象的 options 字段中进行配置,如:
rules: [
    {
        test: /\.jsx?$/,
        use: {
            loader: 'babel-loader',
            options: {
                presets: ["@babel/preset-env"]
            }
        },
        exclude: /node_modules/
    }
]

上面咱们说了如何将JS的代码编译成向下兼容的代码,固然你能够还须要一些其它的 babel 的插件和预设,例如 @babel/preset-react@babel/plugin-proposal-optional-chaining 等,不过,babel 的配置并不是本文的重点,咱们继续往下。

不要说细心的小伙伴了,即便是粗心的小伙伴确定也发现了,咱们在使用 webpack 进行打包的时候,一直运行的都是 npx webpack --mode=development 是否能够将 mode 配置在 webpack.config.js 中呢?显然是能够的。

5.mode

mode 增长到 webpack.config.js 中:

module.exports = {
    //....
    mode: "development",
    module: {
        //...
    }
}

mode 配置项,告知 webpack 使用相应模式的内置优化。

mode 配置项,支持如下两个配置:

  • development:将 process.env.NODE_ENV 的值设置为 development,启用 NamedChunksPluginNamedModulesPlugin
  • production:将 process.env.NODE_ENV 的值设置为 production,启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPluginUglifyJsPlugin

如今,咱们之间使用 npx webpack 进行编译便可。

6.在浏览器中查看页面

搞了这么久,还不能在浏览器中查看页面,这显然不能忍!

查看页面,不免就须要 html 文件,有小伙伴可能知道,有时咱们会指定打包文件中带有 hash,那么每次生成的 js 文件名会有所不一样,总不能让咱们每次都人工去修改 html,这样不是显得咱们很蠢嘛~

咱们可使用 html-webpack-plugin 插件来帮助咱们完成这些事情。

首先,安装一下插件:

npm install html-webpack-plugin -D

新建 public 目录,并在其中新建一个 index.html 文件( 文件内容使用 html:5 快捷生成便可)

修改 webpack.config.js 文件。

//首先引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    //...
    plugins: [
        //数组 放着全部的webpack插件
        new HtmlWebpackPlugin({
            template: './public/index.html',
            filename: 'index.html', //打包后的文件名
            minify: {
                removeAttributeQuotes: false, //是否删除属性的双引号
                collapseWhitespace: false, //是否折叠空白
            },
            // hash: true //是否加上hash,默认是 false
        })
    ]
}

此时执行 npx webpack,能够看到 dist 目录下新增了 index.html 文件,而且其中自动插入了 <script> 脚本,引入的是咱们打包以后的 js 文件。

这里要多说一点点东西,HtmlWebpackPlugin 还为咱们提供了一个 config 的配置,这个配置能够说是很是有用了。

html-webpack-plugin 的 config 的妙用

有时候,咱们的脚手架不只仅给本身使用,也许还提供给其它业务使用,html 文件的可配置性可能很重要,好比:你公司有专门的部门提供M页的公共头部/公共尾部,埋点jssdk以及分享的jssdk等等,可是不是每一个业务都须要这些内容。

一个功能可能对应多个 js 或者是 css 文件,若是每次都是业务自行修改 public/index.html 文件,也挺麻烦的。首先他们得搞清楚每一个功能须要引入的文件,而后才能对 index.html 进行修改。

此时咱们能够增长一个配置文件,业务经过设置 truefalse 来选出本身须要的功能,咱们再根据配置文件的内容,为每一个业务生成相应的 html 文件,岂不是美美的。

Let's Go!

首先,咱们在 public 目录下新增一个 config.js ( 文件名你喜欢叫什么就叫什么 ),将其内容设置为:

//public/config.js 除了如下的配置以外,这里面还能够有许多其余配置,例如,pulicPath 的路径等等
module.exports = {
    dev: {
        template: {
            title: '你好',
            header: false,
            footer: false
        }
    },
    build: {
        template: {
            title: '你好才怪',
            header: true,
            footer: false
        }
    }
}

如今,咱们修改下咱们的 webpack.config.js:

//webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const isDev = process.env.NODE_ENV === 'development';
const config = require('./public/config')[isDev ? 'dev' : 'build'];

modue.exports = {
    //...
    mode: isDev ? 'development' : 'production'
    plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html',
            filename: 'index.html', //打包后的文件名
            config: config.template
        })
    ]
}

相应的,咱们须要修改下咱们的 public/index.html 文件(嵌入的js和css并不存在,仅做为示意):

<!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">
    <% if(htmlWebpackPlugin.options.config.header) { %>
    <link rel="stylesheet" type="text/css" href="//common/css/header.css">
    <% } %>
    <title><%= (htmlWebpackPlugin.options.config.title) %></title>
</head>

<body>
</body> 
<% if(htmlWebpackPlugin.options.config.header) { %>
<script src="//common/header.min.js" type="text/javascript"></script> 
<% } %>
</html>

process.env 中默认并无 NODE_ENV,这里配置下咱们的 package.jsonscripts.

为了兼容Windows和Mac,咱们先安装一下 cross-env:

npm install cross-env -D
{
    "scripts": {
        "dev": "cross-env NODE_ENV=development webpack",
        "build": "cross-env NODE_ENV=production webpack"
    }
}

而后咱们运行 npm run dev 和 运行 npm run build ,对比下 dist/index.html ,能够看到 npm run build,生成的 index.html 文件中引入了对应的 cssjs。而且对应的 title 内容也不同。

你说这里是否是非得是用 NODE_ENV 去判断?固然不是咯,你写 aaa=1aaa=2 都行(固然啦,webpack.config.jsscripts 都须要进行相应修改),可是可能会被后面接手的人打死。

更多html-webpack-plugin配置项

如何在浏览器中实时展现效果

说了这么多,到如今还没能在浏览器中实时查看效果,是否是已经有点捉急了,先看一下如何实时查看效果吧,否则都不知道本身配得对不对。

话很少说,先装依赖:

npm install webpack-dev-server -D

修改下我们的 package.json 文件的 scripts

"scripts": {
    "dev": "NODE_ENV=development webpack-dev-server",
    "build": "NODE_ENV=production webpack"
},

在控制台执行 npm run dev,启动正常,页面上啥也没有,修改下咱们的JS代码,往页面中增长点内容,正常刷新(也就是说不须要进行任何配置就可使用了)。

Excuse me。怪我平时不认真咯,每次都乖乖的配个 contentBase,原来根本不须要配,带着疑问,我又去搜寻了一番。

原来在配置了 html-webpack-plugin 的状况下, contentBase 不会起任何做用,也就是说我之前都是白配了,这是一个悲伤的故事。

不过呢,咱们仍是能够在 webpack.config.js 中进行 webpack-dev-server 的其它配置,例如指定端口号,设置浏览器控制台消息,是否压缩等等:

//webpack.config.js
module.exports = {
    //...
    devServer: {
        port: '3000', //默认是8080
        quiet: false, //默认不启用
        inline: true, //默认开启 inline 模式,若是设置为false,开启 iframe 模式
        stats: "errors-only", //终端仅打印 error
        overlay: "false", //默认不启用
        clientLogLevel: "silent", //日志等级
        compress: true //是否启用 gzip 压缩
    }
}
  • 启用 quiet 后,除了初始启动信息以外的任何内容都不会被打印到控制台。这也意味着来自 webpack 的错误或警告在控制台不可见 ———— 我是不会开启这个的,看不到错误日志,还搞个锤子
  • stats: "errors-only" , 终端中仅打印出 error,注意当启用了 quiet 或者是 noInfo 时,此属性不起做用。 ————— 这个属性我的以为颇有用,尤为是咱们启用了 eslint 或者使用 TS进行开发的时候,太多的编译信息在终端中,会干扰到咱们。
  • 启用 overlay 后,当编译出错时,会在浏览器窗口全屏输出错误,默认是关闭的。

  • clientLogLevel: 当使用内联模式时,在浏览器的控制台将显示消息,如:在从新加载以前,在一个错误以前,或者模块热替换启用时。若是你不喜欢看这些信息,能够将其设置为 silent (none 即将被移除)。

本篇文章不是为了细说 webpack-dev-server 的配置,因此这里就很少说了。关于 webpack-dev-server 更多的配置能够点击查看

细心的小伙伴可能发现了一个小问题,咱们在src/index.js中增长一句 console.log('aaa')

class Animal {
    constructor(name) {
        this.name = name;
    }
    getName() {
        return this.name;
    }
}

const dog = new Animal('dog');
console.log('aaa');

而后经过 npm run dev 查看效果,会发现:

这显然不是咱们源码中对应的行号,点进去的话,会发现代码是被编译后的,我当前的代码很是简单,还能看出来,项目代码复杂后,“亲妈”看编译后都费劲,这不利于咱们开发调试,不是咱们想要的,咱们确定仍是但愿可以直接对应到源码的。

7.devtool

devtool 中的一些设置,能够帮助咱们将编译后的代码映射回原始源代码。不一样的值会明显影响到构建和从新构建的速度。

对我而言,可以定位到源码的行便可,所以,综合构建速度,在开发模式下,我设置的 devtool 的值是 cheap-module-eval-source-map

//webpack.config.js
module.exports = {
    devtool: 'cheap-module-eval-source-map' //开发环境下使用
}

生产环境可使用 none 或者是 source-map,使用 source-map 最终会单独打包出一个 .map 文件,咱们能够根据报错信息和此 map 文件,进行错误解析,定位到源代码。

source-maphidden-source-map 都会打包生成单独的 .map 文件,区别在于,source-map 会在打包出的js文件中增长一个引用注释,以便开发工具知道在哪里能够找到它。hidden-source-map 则不会在打包的js中增长引用注释。

可是咱们通常不会直接将 .map 文件部署到CDN,由于会直接映射到源码,更但愿将.map 文件传到错误解析系统,而后根据上报的错误信息,直接解析到出错的源码位置。

不过报错信息中只有行号,而没有列号。若是有行列号,那么能够经过sourcemap 来解析出错位置。只有行号,根本没法解析,不知道你们的生产环境是如何作的?怎么上报错误信息至错误解析系统进行解析。若有好的方案,请赐教。

还能够设置其余的devtool值,你可使用不一样的值,构建对比差别。

如今咱们已经说了 htmljs 了,而且也能够在浏览器中实时看到效果了,如今就不得不说页面开发三巨头之一的 css

8.如何处理样式文件呢

webpack 不能直接处理 css,须要借助 loader。若是是 .css,咱们须要的 loader 一般有: style-loadercss-loader,考虑到兼容性问题,还须要 postcss-loader,而若是是 less 或者是 sass 的话,还须要 less-loadersass-loader,这里配置一下 lesscss 文件(sass 的话,使用 sass-loader便可):

先安装一下须要使用的依赖:

npm install style-loader less-loader css-loader postcss-loader autoprefixer less -D
//webpack.config.js
module.exports = {
    //...
    module: {
        rules: [
            {
                test: /\.(le|c)ss$/,
                use: ['style-loader', 'css-loader', {
                    loader: 'postcss-loader',
                    options: {
                        plugins: function () {
                            return [
                                require('autoprefixer')({
                                    "overrideBrowserslist": [
                                        ">0.25%",
                                        "not dead"
                                    ]
                                })
                            ]
                        }
                    }
                }, 'less-loader'],
                exclude: /node_modules/
            }
        ]
    }
}

测试一下,新建一个 less 文件,src/index.less:

//src/index.less
@color: red;
body{
    background: @color;
    transition: all 2s;
}

再在入口文件中引入此 less:

//src/index.js
import './index.less';

咱们修改了配置文件,从新启动一下服务: npm run dev。能够看到页面的背景色变成了红色。

OK,咱们简单说一下上面的配置:

  • style-loader 动态建立 style 标签,将 css 插入到 head 中.
  • css-loader 负责处理 @import 等语句。
  • postcss-loaderautoprefixer,自动生成浏览器兼容性前缀 —— 2020了,应该没人去本身徒手去写浏览器前缀了吧
  • less-loader 负责处理编译 .less 文件,将其转为 css

这里,咱们之间在 webpack.config.js 写了 autoprefixer 须要兼容的浏览器,仅是为了方便展现。推荐你们在根目录下建立 .browserslistrc,将对应的规则写在此文件中,除了 autoprefixer 使用外,@babel/preset-envstylelinteslint-plugin-conmpat 等均可以共用。

注意:

loader 的执行顺序是从右向左执行的,也就是后面的 loader 先执行,上面 loader 的执行顺序为: less-loader ---> postcss-loader ---> css-loader ---> style-loader

固然,loader 其实还有一个参数,能够修改优先级,enforce 参数,其值能够为: pre(优先执行) 或 post (滞后执行)。

如今,咱们已经能够处理 .less 文件啦,.css 文件只须要修改匹配规则,删除 less-loader 便可。

如今的一切看起来都很完美,可是假设咱们的文件中使用了本地的图片,例如:

body{
    backgroud: url('../images/thor.png');
}

你就会发现,报错啦啦啦,那么咱们要怎么处理图片或是本地的一些其它资源文件呢。不用想,确定又须要 loader 出马了。

9.图片/字体文件处理

咱们可使用 url-loader 或者 file-loader 来处理本地的资源文件。url-loaderfile-loader 的功能相似,可是 url-loader 能够指定在文件大小小于指定的限制时,返回 DataURL,所以,我的会优先选择使用 url-loader

首先安装依赖:

npm install url-loader -D

安装 url-loader 的时候,控制台会提示你,还须要安装下 file-loader,听人家的话安装下就行(新版 npm 不会自动安装 peerDependencies):

npm install file-loader -D

webpack.config.js 中进行配置:

//webpack.config.js
module.exports = {
    //...
    modules: {
        rules: [
            {
                test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 10240, //10K
                            esModule: false 
                        }
                    }
                ],
                exclude: /node_modules/
            }
        ]
    }
}

此处设置 limit 的值大小为 10240,即资源大小小于 10K 时,将资源转换为 base64,超过 10K,将图片拷贝到 dist 目录。esModule 设置为 false,不然,<img src={require('XXX.jpg')} /> 会出现 <img src=[Module Object] />

将资源转换为 base64 能够减小网络请求次数,可是 base64 数据较大,若是太多的资源是 base64,会致使加载变慢,所以设置 limit 值时,须要两者兼顾。

默认状况下,生成的文件的文件名就是文件内容的 MD5 哈希值并会保留所引用资源的原始扩展名,例如我上面的图片(thor.jpeg)对应的文件名以下:

固然,你也能够经过 options 参数进行修改。

//....
use: [
    {
        loader: 'url-loader',
        options: {
            limit: 10240, //10K
            esModule: false,
            name: '[name]_[hash:6].[ext]'
        }
    }
]

从新编译,在浏览器中审查元素,能够看到图片名变成了: thor_a5f7c0.jpeg

当本地资源较多时,咱们有时会但愿它们能打包在一个文件夹下,这也很简单,咱们只须要在 url-loaderoptions 中指定 outpath,如: outputPath: 'assets',构建出的目录以下:

更多的 url-loader 配置能够查看

到了这里,有点岁月静好的感受了。

不过还没完,若是你在 public/index.html 文件中,使用本地的图片,例如,咱们修改一下 public/index.html

<img src="./a.jpg" />

重启本地服务,虽然,控制台不会报错,可是你会发现,浏览器中根本加载不出这张图片,Why?由于构建以后,经过相对路径压根找不着这张图片呀。

How?怎么解决呢?

10.处理 html 中的本地图片

安装 html-withimg-loader 来解决咯。

npm install html-withimg-loader -D

修改 webpack.config.js

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

而后在咱们的 html 中引入一张文件测试一下(图片地址本身写咯,这里只是示意):

<!-- index.html -->
<img src="./thor.jpeg" />

重启本地服务,图片并没能加载,审查元素的话,会发现图片的地址显示的是 {"default":"assets/thor_a5f7c0.jpeg"}

我当前 file-loader 的版本是 5.0.2,5版本以后,须要增长 esModule 属性:

//webpack.config.js
module.exports = {
    //...
    modules: {
        rules: [
            {
                test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 10240, //10K
                            esModule: false
                        }
                    }
                ]
            }
        ]
    }
}

再重启本地服务,就搞定啦。

话说使用 html-withimg-loader 处理图片以后,html 中就不能使用 vm, ejs 的模板了,若是想继续在 html 中使用 <% if(htmlWebpackPlugin.options.config.header) { %> 这样的语法,可是呢,又但愿能使用本地图片,可不能够?鱼和熊掌都想要,虽然不少时候,能吃个鱼就不错了,可是这里是能够的哦,像下面这样编写图片的地址就能够啦。

<!-- index.html -->
<img src="<%= require('./thor.jpeg') %>" />

图片加载OK啦,而且 <% %> 语法也能够正常使用,吼吼吼~~~

虽然,webpack 的默认配置很好用,可是有的时候,咱们会有一些其它须要啦,例如,咱们不止一个入口文件,这时候,该怎么办呢?

11.入口配置

入口的字段为: entry

//webpack.config.js
module.exports = {
    entry: './src/index.js' //webpack的默认配置
}

entry 的值能够是一个字符串,一个数组或是一个对象。

字符串的状况无需多说,就是以对应的文件为入口。

为数组时,表示有“多个主入口”,想要多个依赖文件一块儿注入时,会这样配置。例如:

entry: [
    './src/polyfills.js',
    './src/index.js'
]

polyfills.js 文件中可能只是简单的引入了一些 polyfill,例如 babel-polyfillwhatwg-fetch 等,须要在最前面被引入(我在 webpack2 时这样配置过)。

那何时是对象呢?不要捉急,后面将多页配置的时候,会说到。

12.出口配置

配置 output 选项能够控制 webpack 如何输出编译文件。

const path = require('path');
module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'), //必须是绝对路径
        filename: 'bundle.js',
        publicPath: '/' //一般是CDN地址
    }
}

例如,你最终编译出来的代码部署在 CDN 上,资源的地址为: 'https://AAA/BBB/YourProject/XXX',那么能够将生产的 publicPath 配置为: //AAA/BBB/

编译时,能够不配置,或者配置为 /。能够在咱们以前说起的 config.js 中指定 publicPathconfig.js 中区分了 devpublic), 固然还能够区分不一样的环境指定配置文件来设置,或者是根据 isDev 字段来设置。

除此以外呢,考虑到CDN缓存的问题,咱们通常会给文件名加上 hash.

//webpack.config.js
module.exports = {
    output: {
        path: path.resolve(__dirname, 'dist'), //必须是绝对路径
        filename: 'bundle.[hash].js',
        publicPath: '/' //一般是CDN地址
    }
}

若是你以为 hash 串太长的话,还能够指定长度,例如 bundle.[hash:6].js。使用 npm run build 打包看看吧。

问题出现啦,每次文件修改后,从新打包,致使 dist 目录下的文件愈来愈多。要是每次打包前,都先清空一下目录就好啦。可不能够作到呢?必须能够!

13.每次打包前清空dist目录

反正我是懒得手动去清理的,只要你足够懒,你老是会找到好办法的,懒人推进科技进步。这里,咱们须要插件: clean-webpack-plugin

安装依赖:

npm install clean-webpack-plugin -D

之前,clean-webpack-plugin 是默认导出的,如今不是,因此引用的时候,须要注意一下。另外,如今构造函数接受的参数是一个对象,可缺省。

//webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    //...
    plugins: [
        //不须要传参数喔,它能够找到 outputPath
        new CleanWebpackPlugin() 
    ]
}

如今你再修改文件,重现构建,生成的hash值和以前dist中的不同,可是由于每次 clean-webpack-plugin 都会帮咱们先清空一波 dist 目录,因此不会出现太多文件,傻傻分不清楚究竟哪一个是新生成文件的状况。

但愿dist目录下某个文件夹不被清空

不过呢,有些时候,咱们并不但愿整个 dist 目录都被清空,好比,咱们不但愿,每次打包的时候,都删除 dll 目录,以及 dll 目录下的文件或子目录,该怎么办呢?

clean-webpack-plugin 为咱们提供了参数 cleanOnceBeforeBuildPatterns

//webpack.config.js
module.exports = {
    //...
    plugins: [
        new CleanWebpackPlugin({
            cleanOnceBeforeBuildPatterns:['**/*', '!dll', '!dll/**'] //不删除dll目录下的文件
        })
    ]
}

此外,clean-webpack-plugin 还有一些其它的配置,不过我使用的很少,你们能够查看clean-webpack-plugin

至此,咱们算是完成了一个基础配置。可是这不够完美,或者说有些时候,咱们还会有一些其它的需求。下一篇关于webpack配置的文章会介绍一些其它的状况。

最后

若是本文对你有帮助的话,给本文点个赞吧。

参考资料
相关文章
相关标签/搜索