美文网首页技术干货我的大学webpack
从0到1教你学习并配置webpack

从0到1教你学习并配置webpack

作者: Cryptic | 来源:发表于2019-12-31 20:14 被阅读0次

    抓住2019年的尾巴,迎接2020年的到来~

    给自己的2019年画上一个完美的句号。

    引言

    webpack 对于现在的前端开发的你来说,不算陌生,你或许没有真正去了解过它是如何使用的,但你的项目中确实使用过它,因为你项目的打包编译都跟他息息相关~

    前阵子刚好在研究webpack以及其源码相关的知识,如果你跟我一样,好奇webpack又是怎么工作的?那些奇奇怪怪的配置都是什么东西?分别代表什么意思?

    那你不妨花几分钟阅读一下,跟我一起学习回顾一下如何从0到1去了解webpack的知识, 配置你项目需要的webpack~

    pass:本文以 webpack4 为例~

    什么是webpack?

    什么是 webpack

    官方文档 是这么说:

    webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle

    其实,它就是一个模块化打包工具,它所做的事情就是分析你的项目结构,找到JavaScript模块并对其进行代码转换(scss 转换为cssTypescript 转换为 Javscript),文件优化(压缩JavaScriptCSSHTML、图片等),模块合并 (把模块分类合并成一个文件)等一系列的操作,最终打包为合适的格式在让你的项目可以在浏览器中运行~

    盗用官网的一张图,其主要工作原理就如下图所示~

    核心概念

    在真正上手 webpack 之前,我们需要对其几个 核心概念 有所了解

    • Entry:入口路径,webpack执行构建的第一步的输入文件。

    • Module:模块,在 webpack 里一切皆模块,一个模块对应着一个文件,webpack 会从配置的 Entry 开始递归找出所有依赖的模块。

    • Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。

    • Loader:模块转换器,用于把模块原内容按照需求转换成新内容,例如scsscss的转换等,构建模块的第一步就是使用loader来加载并处理模块内容

    • Plugin:扩展插件,webpack 的重要组成部分,其 webpack 源码的很多核心功能也都是插件实现的,由于webpack提供了在不同的生命周期内提供了很多不同的hooks钩子函数,插件的工作原理就是在 webpack 构建流程中的不同的(hooks)时机注入扩展逻辑来改变构建结果或做个性化操作。

    • Output:输出结果,在 webpack 经过一系列处理后最终代码后输出配置。

    整个流程串起来大概就是:

    webpack启动后会从Entry里配置的Module开始递归解析 Entry 依赖的所有 Module。 每找到一个 Module,就会根据配置的Loader去找出对应的转换规则,对 Module 进行转换后,再解析出当前 Module 依赖的 Module

    这些模块会以 Entry 为单位进行分组,一个 Entry 和其所有依赖的 Module 被分到一个组也就是一个Chunk。最后 webpack 会把所有 Chunk 转换成文件输出,在这整个流程中 webpack 会在不同的生命周期内执行配置的 Plugin 里定义的逻辑。

    了解了上面的一些概念和流程之后,接下来,我们一步步来配置,打包我们的项目~

    初始化项目

    创建文件夹

    首先,我们创建一个你喜欢的文件夹,并通过 npm init -y 来初始化项目配置,并在其目录下创建一个我们源代码的目录src和一个打包后的文件输入目录dist

    创建入口文件 index.js

    然后我们在 src 目录下创建一个 index.js 文件,作为我们的打包入口文件,并写上我们熟悉的 console.log('hello world'); 作为打包内容。

    安装webpack

    webpack4 之后将 webpackcli 分成了两个包,我们需要通过 npm install webpack webpack-cli -D 安装我们所需的 webpack 依赖。

    ok~ 准备就绪!

    遗憾的是,你还是不能直接进行打包,因为我们的 webpack 是在项目下安装的,所以不能直接运行,想要正确运行webpakc我们可以有下面2种方式:

    • 使用 npx 命令,可以直接运行 node_modules/.bin 目录下的命令
    • 通过配置 package.json 中的 scripts 脚本命令进行执行

    为了贴近我们的项目,这里我们选择第二种方式

    配置package.json脚本

    我们打开package.json文件,并在 scripts 中配置下面的代码:

        "dev" : "webpack --mode development",
        "build" : "webpack --mode production",
    

    dev 表示开发模式,build 是生产模式,不同在于 dev 会有很多方便我们开发调试的功能,比如代码不压缩混淆,有开发服务器之类的,我们学习阶段采用 dev 即可~

    创建配置文件

    这时候,我们已经可以通过 npm run dev 命令打包我们的代码,并在dist目录下看到我们打包后的 main.js 文件了~

    你可能很诧异的蹦出一句:

    因为到此,你发现自己什么都还没配置,咋就可以打包了!!

    这是因为 webapck4 为了简化我们开发人员繁琐的配置工作,在内部写好了一套配置,惊不惊喜,意不意外!!

    那我这肯定不能答应了,不然不就打我脸了么!

    要想加载自己的配置,我们需要在我们的项目根目录下创建 webpack.config.js 文件,并创建我们的基础配置。

    //path
    const path = require('path');
    
    //配置信息
    module.exports = {
        //入口文件
        entry : './src/index.js' ,
        //出口文件
        output : {
            //打包后路径,只能写绝对路径
            path : path.resolve(__dirname,'dist'),
            //打包后文件名
            filename : '[name].[hash].js'
        },
        //模块转换规则
        module : {
        
        },
        //插件
        plugins : [
        
        ],
        //开发服务器
        devServer : {
        
        }
    }
    

    我们注意到 output 中的 filename 中有一个 [name][hash],其中nameentry 的名字,默认是 mainhash 是打包根据内容后计算出的一个 hash值,保证文件的唯一性,可以通过[hash:8] 表示取其前8位。

    现在运行 npm run devdist 目录下就会打包出类似 main.47bfc309d4ba9b75d346.js 的文件。

    这里,我们为了方便,先将其改成 main.js

    创建index.html文件

    为了方便我们在浏览器测试,我们在我们的 dist 目录创建一个 index.html ,并引入我们编译好的main.js文件,如下:

    //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>webpack</title>
    </head>
    <body>
    <div id="app">webpack</div>
    <script src="main.js"></script>
    </body>
    </html>
    
    

    我们在 index.js 文件下加上这么一句话:

    document.querySelector('#app').style.color='red';

    测试一下打包后的文件好不好使。

    运行 npm run dev,打开我们的 index.html 预览,不出意外的话,结果应该和我一样,页面的 webpack 文字变红,控制台输出 hello world

    至此,我们才将我们的项目基础配置搞定~

    加载css

    如果我们现在想加入 css 文件,优化我的样式,首先在 src 目录下创建 stylesheets 目录,并添加 index.css 文件,我们就先以 body { background : #f2f2f2; } 为例,之后在 index.js 中通过 import './stylesheets/index.css' 的方式导入样式文件。

    如果现在我们直接进行打包肯定会报错,因为 css 文件并不是 js 模块,webpack 在打包的时候没法直接处理,需要借助转换工具,这转换工具就是 Loader

    • 什么是 Loader

    Loader 就是文件转换器,通过使用不同的Loaderwebpack就可以把不同的文件都转成js文件,比如CSSES6/7JSX等,它通常有下面几个配置项:

    • test:匹配处理文件的扩展名的正则表达式
    • useloader名称,就是你要使用模块的名称
    • include/exclude:手动指定必须处理的文件夹或屏蔽不需要处理的文件夹
    • query:为loaders提供额外的设置选项

    接下来,我们来使用 style-loadercss-loader 来处理我们的 css 文件。

    执行 npm install style-loader css-loader -D 进行安装 loader

    webpack.config.js 中的module下面添加解析规则:

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

    通常来说,loader有下面三种书写方式,上面是通过 use 方式,还有两种方式分别是 直接使用 loader 和使用 use + loader

    //直接使用loader
    
    module: {
        rules: [{
            test: /\.css/,
            loader:['style-loader','css-loader']
        }]
    }
    
    //use + loader 的方式
    
    module: {
        rules: [{
            test: /\.css/,
            include: path.resolve(__dirname,'src'),
            exclude: /node_modules/,
            use: [{
                loader: 'style-loader',
                options: {
                    insert:'top'
                }
            },'css-loader']
        }]
    }
    

    要注意的是配置多个 loader有顺序 的,webpack 会安装配置的 loader 顺序 从右向左 执行的,配置的时候要格外注意!

    拿我们上面的 style-loadercss-loader 来说,两个loader配置的顺序不可调换,因为 css-loader是解析处理css里的url路径,并将css文件转换成一个模块,style-loader是 将css文件变成style标签插入到head中的。

    现在我们 npm run dev 试试,打包没有报错,预览 index.html 也成功生效,很赞!

    配置开发服务器

    到此你有没有发现,我们在平时的开发过程中,怎么没有遇到说让我每次通过预览dist下的 index.html来看我们打包效果的,这是由于我们平时的开发中会在自己本地起一个服务器,来帮我们做这件事。

    现在,我们也来试试~

    • 通过 npm i webpack-dev-server –D 安装我们的开发服务器依赖
    • 修改我们的启动脚本,将原来的 package.json 中的 dev 脚本修改为 webpack-dev-server --open ,其中 --open 是自动打开浏览器的意思

    此时,直接运行 npm run dev 是看不到我们预期的效果的,因为我们还没有对我们的服务器进行配置。

    我们在 webpack.config.jsdevServer 下添加如下配置:

    devServer : {
        contentBase : path.resolve(__dirname,'dist'),
        host : 'localhost' ,
        port : 8000 ,
        compress : true
    }
    
    • contentBase 配置开发服务运行时的文件根目录,也就是静态资源访问地址
    • host 开发服务器监听的主机地址
    • port 开发服务器监听的端口,默认是 8080
    • compress 开发服务器是否启动gzip等压缩

    ok,运行 npm run dev ,是不是效果非常棒!

    要注意的是,webpack dev server 产生的打包文件是在 内存中!,是 内存中!,硬盘是访问不到的,怎么验证这一点呢?

    很简单,你可以删除掉你dist目录下的 main.js ,重新运行 npm run dev ,你可以看到 dist 目录下并没有 main.js,但你访问 localhost:8000 确实能正确访问,并且访问 http://localhost:8000/main.js 也能看到打包后的源码,证明它产生的打包文件确实是在你的 内存中

    注意,我们这里打包出来的只有一个 main.js 文件和一个index.css文件,index.html 文件是我们手动添加进去的,不是打包产生的,如果删掉 index.html 是无法正确访问页面的,内存里可没有 index.html 文件。

    我们可以在终端看到以下这些内容:

    这些都是我们在启动开发服务器的时候 webpack 给我们的页面注入的 websocket 连接,你可以在你的页面调试器的 network 中的 ws 里看到,

    其重要作用就是,监控你文件的变化,可以帮助你重新刷新页面,让你看到更改后的效果,你可以修改一下 index.js 文件试试~

    自动生产HTML文件

    我们之前是在 dist 目录下写好了 index.html 文件,并在里面通过 script 标签引入我们打包后的内容,即 main.js ~

    还记得我们之前打包后的 filename 中可以加入一个 hash 值也区别不同的文件,如果 hash 值发生变化了,我们的 index.html 岂不是找不到资源了?所以我们希望自动能产出HTML文件,并在里面引入产出后的资源,这样就不必为上面的问题担心了。

    我们删除掉 dist 目录下的 index.html 文件,并在 src 目录下创建一个 index.html 文件,我们称它为模板,以它为模板产生 html 文件。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
        <title>webpack</title>
    </head>
    <body>
        <div id="app">webpack</div>
    </body>
    </html>
    

    这时,我们需要接触到第一个插件 html-webpack-plugin!

    之前也说了,插件在 webpack 中有很重要的作用,在 webpack 的构建流程中,plugin 用于处理更多其他的一些构建任务,模块代码转换的工作由 loader 来处理,除此之外的其他任何工作都可以交由 plugin 来完成。

    • 首先我们需要通过 npm install html-webpack-plugin -D 去安装它。
    • 然后在 webpack.config.jsplugins 下去配置它(需要先通过 require 引入)
    //自动产出HTML模版
    new HtmlWebpackPlugin({
        template: './src/index.html',
        filename: 'index.html',
        hash: true,
        minify: {
            removeAttributeQuotes: true,
            removeComments: true 
        }
    })
    

    其中 template 是指定模板文件,filename 是指定产出后的文件名,hash 是为了避免缓存,可以在产出的资源后面添加hash值,minify 是 压缩相关的配置,minify.removeAttributeQuotes 是为了去掉属性的双引号,minify.removeComments 是为了压缩文件,删除模板中的注释。

    此时,我们运行 npm run dev 访问 localhost:8000 发现已经可以正常访问了,但是 dist 目录下却没有任何东西,因为我们之前提到了,开发服务器打包的文件是写入内存中的,不是硬盘里。

    为了方便我们看效果,我们在 package.json 中的 scripts 中在增加一行 "dev-build": "webpack --mode development" 用来打包我们开发环境的代码。

    运行 npm run dev-build 脚本,完成之后可以发现 dist 目录已经打包出来了 index.html 文件 和 main.[hash].js 文件,打开 index.html 文件可以发现标签的双引号已经没去掉了,并且引入的脚本也自动加上了 ?[hash] 值。

    <!DOCTYPE html>
    <html lang=en>
    <head>
        <meta charset=UTF-8>
        <meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
        <title>Title</title>
    </head>
    <body>
        <div id=app>webpack</div>
    <script type=text/javascript src=main.e6570abab6c2814d1608.js?e6570abab6c2814d1608></script></body>
    </html>
    

    预览 index.html 文件,一切也都正常。

    passwebpack4以后,如果你看到终端输入有下面这么怪异的一行,

    而正巧你又是一个 强迫症患者,在 webpack.config.js 中添加 stats: { children: false } 即可。

    支持图片

    前端项目中肯定少不了图片资源,如果我们直接在 css 或者 js 文件中引入图片资源去打包,那么肯定是通不过了,因为 webpack 无法识别图片资源,因为图片也不是一个有效的模块。

    此时,我们需要引入这个两个 loader 去解决它, file-loader url-loaderfile-loader 解决CSS等文件中的引入图片路径问题,url-loader 当图片小于limit的时候会把图片base64编码,大于limit参数的时候还是使用file-loader 进行拷贝

    • 通过 npm install file-loader url-loader -D 下载依赖
    • src目录下创建一个 images 文件夹,存放几张你喜欢的图片
    • index.jsindex.css 中引入图片,并将其插入到页面中去(我这里以本地的 avatar.jpgscene.jpg 为例)
    //index.js
    import Avatar from './images/avatar.jpg'
    
    let img = new Image();
    
    img.src = Avatar;
    
    document.body.appendChild(img);
    
    //index.css
    
    body{
        background-color: #f2f2f2;
        background-image: url("../images/scene.jpg");
        background-repeat: no-repeat;
    }
    
    • webpack.config.js中的module下面添加如下配置
    {
        test:/\.(png|jpg|gif|svg|bmp)$/,
        use:{
            loader: 'url-loader',
            options: {
                limit: 10 * 1024,
                outputPath: 'images/'
            }
        }
    }
    

    options 中的 limit 就是图片的限制,这里我指定的是 10kb ,小于 10kb 的图片会以 base64 编码输出,outputPath 指定了拷贝文件输出目录,默认是dist目录下。

    现在我们 npm run dev-build 走一波~

    也不报错,运行 index.html 文件,也很正常!

    编译less 和 sass

    现在开发过程中,为了简化我们书写 css 的过程,我们一般项目中引入了 lesssass 这样的预加载器~

    同样的你不处理之前 webpack 是不认识 lesssass 文件的,毕竟它不是一个 js 模块,我们通过需要借助 less-loadersass-loader 来处理这些文件~

    • 通过运行 npm install less less-loader -D npm install node-sass sass-loader -D 分别安装 loader
    • webpack.config.js中添加loader解析规则
    {
        test: /\.less/,
        use: ['style-loader', 'css-loader', 'less-loader']
    }, {
        test: /\.scss/,
        use: ['style-loader', 'css-loader', 'sass-loader']
    }
    

    这样,你就可以放心在你的项目里引入 css 预处理了~

    分离css

    因为CSS的下载和js可以并行,当一个HTML文件很大的时候,那么页面加载肯定会非常慢,那么我们希望可以把CSS单独提取出来加载,为每个包含 CSSJS 文件创建一个 CSS 文件,按需加载。

    我们需要 mini-css-extract-plugin 这么一个插件

    • 通过 npm install mini-css-extract-plugin -D 安装模块依赖
    • webpack.config.jsplugins 下去配置一下
    new MiniCssExtractPlugin({
        filename: 'css/[name].[hash].css',
        chunkFilename: "css/[id].css"
    })
    

    除此之外,我们的还需要做一个操作就是将我们之前处理cssstyle-loader 改写成下面这种形式:

    {
        test: /\.css$/,
        use: [{
            loader: MiniCssExtractPlugin.loader
        }, 'css-loader']
    },{
        test: /\.less/,
        use: [{
            loader: MiniCssExtractPlugin.loader
        }, 'css-loader', 'less-loader']
    }, {
        test: /\.scss/,
        use: [{
            loader: MiniCssExtractPlugin.loader
        }, 'css-loader', 'sass-loader']
    }
    

    趁热打铁,赶紧来试试,npm run dev-build 进行打包~

    预览 index.html 页面,打开控制台network可以发现下载文件的时候多出了一个 main.css 文件,并且我们 htmlhead 头,已经换成了 link 方式,并且你的 dist 目录下会多出一个 css 的文件夹,里面存放打包后的 css 文件。

    tips: 如果你在外部的css 文件中文件中引入图片,而图片放在了images目录下,那么打包上线后的图片会出现 404 的情况,你可以查看打包后的 css 文件,就可以反向是路径的问题,需要配置一下 publicPath 即可~

    {
        loader: MiniCssExtractPlugin.loader,
        options: {
            publicPath: '/'
        }
    }
    

    注意,这个一般是在 服务器 上会出现,本地打包后没有起服务也是看不到的。

    处理CSS3属性前缀

    我们在书写 css 的时候,为了浏览器的兼容性,有时候我们必须加入-webkit-ms-o-moz这些浏览器前缀,但我们又不想去书写这些繁琐的东西,这时候可以交给我们 postcss 来处理~

    postcss的主要功能只有两个:

    • 第一个就是前面提到的把 CSS 解析成 JavaScript 可以操作的 抽象语法树结构(Abstract Syntax Tree,AST)
    • 第二个就是调用插件来处理 AST 并得到结果

    我们首先通过 npm install postcss-loader autoprefixer -D 来安装依赖

    想要这个 postcss 正常工作,我们需要配置两个东西

    • 在根目录下创建 postcss.config.js 配置文件,表示使用 autoprefixer 来进行补全
    module.exports={
        plugins:[require('autoprefixer')]
    }
    
    • webpack.config.js 中修改并添加对css处理的 loader
    {
        test: /\.css$/,
        use: [{
            loader: MiniCssExtractPlugin.loader
        }, 'css-loader', 'postcss-loader'],
        include: path.join(__dirname, './src'),
        exclude: /node_modules/
    }
    

    这里我在我的 index.css 中添加了如下测试代码:

    //index.css
    ::placeholder {
        color: orange;
    }
    

    并在我的 index.js 中创建了一个 input 控件:

    //index.js
    
    let input = document.createElement('input');
    document.body.appendChild(input);
    

    运行 npm run dev-build 打包,预览 index.html ,打开调试工具的的 sources板块,查看 main.css , 发现对应的前缀已添加,并且我页面的 input 已经变成了 orange~

    转义ES6/ES7

    虽然 es6es7 的代码我们已经或多或少都在项目中,但是大部分浏览器对于 es6es7 代码的支持度并不高,很大部分的浏览器还是只能解析 es5 的代码,为了让我们能正常使用 es6es7的代码,我们需要借助 webpack 对其进行转义,转成 es5 代码。

    我们需要借助 babel 这个工具,它是一个编译JavaScript的平台,可以把ES6/ES7的代码转义为ES5代码。

    • 通过 npm install babel-loader @babel/core @babel/preset-env -D 安装依赖
    • webpack.config.js 中添加 babel-loader ,因为 babel-loader只是告诉了 webpack 怎么处理 ES6ES7 代码,但它并不会将 ES6ES7 代码翻译成向后兼容版本的代码,因此需要指定一个 preset,它包含了代码转换的规则
    {
        test: /\.js$/,
        loader : 'babel-loader' ,
        exclude:'/node_modules/'
    }
    
    • 在我们的项目根目录创建一个 .babelrc 的文件来配置,用来配置我们的 babel 相关
    {
      "presets": [
        [
          "@babel/preset-env",
          {
            "targets": {
              "browsers": [
                "> 1%",
                "last 2 versions"
              ]
            },
            "debug":true //调试使用
          }
        ]
      ]
    }
    
    • 我们在 index.js 文件中添加以下代码测试一下,并打包测试一下:
    const test = (n)=> {
        return new Promise(function (resolve) {
            setTimeout(()=>{
                resolve([1,2,3,4].map(v=>v * v ))
            },n*1000)
        }).then(res=>{
            console.log(res);
        })
    }
    
    console.log(test)
    

    查看打包后的文件,发现转换的不够彻底,只能针对语法进行了转换,对于 Promisemap 这些高级用法并没有被转换,这肯定是不行的,我们还要想办法把这些新的特性,兼容到低版本的浏览器里。

    我们还需要 babel 提供的另一个工具—— polyfill

    • npm install @babel/polyfill -D 安装它
    • 在我们的入口文件 index.js 最顶部添加 import '@babel/polyfill'
    • 运行 npm run dev-build 编译打包,虽然控制台好想没啥变化,但是我们的打包的文件 main.js 发生了很大变化,很明显的一点,体积大了好几十倍

    这是由于为了兼容低版本浏览器,polyfill 里面添加了很多辅助代码来帮助实现比如 Promisemap 这些新特性,默认情况下会被添加到每一个需要它的文件中,并且会全局注入,造成全局污染,如果我们在开发框架之类的,可能会发生冲突。

    我们加了 debug 可以在终端看到,确实是加入了不少插件:

    为了解决这个问题,我们引入 @babel/runtime 这个模块,来避免重复导入的问题
    如果是写第三方库或者框架

    • 运行 npm install @babel/runtime @babel/plugin-transform-runtime -D安装模块依赖
    • 配置@babel/runtime,并修改一下 preset-env的配置,加上 useBuiltIns: 'usage' ,表示会根据业务需求自动转换需要转换的新语法
    {
      "presets": [
        [
          "@babel/preset-env",
          {
            "useBuiltIns": "usage",
            "targets": {
              "browsers": [
                "> 1%",
                "last 2 versions"
              ]
            },
            "debug":true //调试使用
          }
        ]
      ],
      "plugins": [
        [
          "@babel/plugin-transform-runtime",
          {
            "corejs": false,
            "helpers": true,
            "regenerator": true,
            "useESModules": true
          }
        ]
      ]
    }
    
    • 配置完成,ok,我们再来运行 npm run dev-build 打包一次试试

    终端日志可以看到注入的辅助代码大幅度较少,文件的大小也大幅度减少,赞!

    拷贝静态文件

    我们有些项目中的文件,不是 js ,也不是 css , 图片之类的,比如 README.md这些静态资源,我也希望能打包到我的项目里,怎么办呢?

    其实就是文件的拷贝操作,我们只需要将这些文件拷贝到目标目录下即可,我们可以利用 copy-webpack-plugin 这个插件

    • 运行 npm run copy-webpack-plugin -D 安装插件
    • 在项目目录下创建一个 static/README.md 的测试文件
    • 修改 webpack.config.js , 将插件添加到配置里去
    new CopyWebpackPlugin({
        from: path.resolve(__dirname,'src/static'),
        to:path.resolve(__dirname,'dist/static') 
    })
    

    from 是静态资源目录源地址,to是要拷贝文件的目标地址,so easy~

    npm run dev-build 打包运行!

    可以发现我们的 dist 目录已经将 src/static 的文件拷贝到了 dist/static

    打包前清空

    我们修改了文件之后,每次打包都会在 dist 目录下产生一个新的 main.[hash].js , 随着我们打包次数的增加,dist 目录下会生产出一堆的 main.[hash].js,不出意外,你的dist目录应该已经有不少了~

    为了保证我们每次看到的都是最新的打包资源,而不受之前打包文件的干扰,这里我们需要引入另一个插件—— clean-webpack-plugin

    • 通过 npm install clean-webpack-plugin -D 下载插件
    • webpack.config.jsplugins 下去配置它
    plugins:[
        new CleanWebpackPlugin()
    ]
    

    pass:该插件引入方式是稍微有点不同,通过以下这种方式引入:

    const { CleanWebpackPlugin } = require('clean-webpack-plugin')

    现在,每次打包前都会先清空 dist 目录下的文件,然后才产出打包后的文件,这样看起来就清晰多了!

    服务器代理

    我们在开发时,有时候希望在同域名下发送 API 请求 ,那么代理某些 URL 会很有用,代理 API 的配置对于 webpack来说,配置就非常简单了,只需要在 proxy 中添加代理规则即可

     proxy :  {
        "/api/test": {
         target: 'http://lohost:3000/', 
         secure: false,  
         changeOrigin: true, 
         pathRewrite: {
           '^/api/test': '/test'
        }
    }
    
    

    上面这行配置,就可以将 /api/test 开头的接口地址,会被代理到 http://localhost:3000/test 下,如果是https接口,需要配置 secure 这个参数 为 true ,如果接口跨域,需要配置changeOrigin这个参数为 true

    压缩JS和CSS

    我们现在打包出来的文件无论是 jscss 都是源文件,我们希望在打包的时候压缩我们的代码,一来是为了安全,二来是可以减少我们打包文件的体积。

    我们选择使用terser-webpack-plugin来压缩js文件,替换掉之前的 uglifyjs-webpack-plugin,解决uglifyjs不支持es6语法问题,使用 optimize-css-assets-webpack-plugin 来压缩 css 文件

    • 运行 npm install terser-webpack-plugin optimize-css-assets-webpack-plugin -D安装插件
    • webpack.config.js 中引入并配置插件
    new TerserPlugin({
        parallel: true,
        cache: true
    }),
    new OptimizeCSSAssetsPlugin({
        assetNameRegExp:/\.css$/g,
        cssProcessor:require('cssnano')
    })
    

    TerserPlugin 中的 parallel 代表开启多进程,cache 代表设置缓存,OptimizeCSSAssetsPlugin 中加载了一个 cssnano 的东西, cssnanoPostCSSCSS优化和分解插件,会自动采用格式很好的CSS,并通过许多优化,以确保最终的生产环境尽可能小。

    现在我们在继续打包一次!

    查看我们打包后的文件,可以发现 jscss 文件都没打包成了一行,搞定!

    结语

    ok~ 看到这里,想必你对 webpack 已经有了一个比较完善的认识,对常见的一些配置打包的 loader 或者 plugin 都有一定的了解了,总结会发现,套路基本都差不多,需要什么 loaderplugin 只要去对应去查找即可~

    emmm,其实 webpack 的功能非常强大,配置也是相当的多样化,这里只是列举了一些比较常见的功能,对你来说也只是一个抛砖引玉的作用,它的内部实现也是相当的复杂,想要真正弄懂 webpack ,还是需要多下一番苦功夫的~

    对了,2019年还有几个小时就结束了~

    2020年,加油~

    相关文章

      网友评论

        本文标题:从0到1教你学习并配置webpack

        本文链接:https://www.haomeiwen.com/subject/hreioctx.html