姗姗来迟的webpack4.0+实战

1,106 阅读4分钟

前言

不讲概念性的东西,直接进入实战开发,目的让你在实践中领悟,然后再去理解概念,会事半功倍,减轻阅读成本和心理压力。为了阅读脉络更清晰,我会从3W1H原则去行文。

  • what --------做什么
  • who --------谁来做
  • when--------什么时候做
  • how---------怎么做)

背景

2019最后一篇技术文章,也是webpack4.41.5的最新落地版本,希望这篇文章能够让你真正的会用webpack4.0+,然后根据自己的理解和官网的文章、参照其他概念性的文章进阶,下面我们就一起动手实现我们的webpack脚手架吧,一起跨越2019迎接2020。

简单定义

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。 上面如果你不知道什么意思,没关系,我们直接进入实战,跟着本文亲手做一遍,或者所有的demo下载到本地跑一遍,你就理解了,如果还是不理解欢迎骚扰,文后关注我,后续解答。

实战

npx webpack打包

  • what: 打包资源
  • who: npx
  • when: 执行npx webpack脚本打包资源的时候
  • how: 当前项目命令工具下执行 npx webpack
  • 项目地址: webpack-demo-4.41.5-npx-webpack

配置webpack打包

  • what: 配置的方式打包资源
  • who: package.json下script中配置命令行
  • when: 运行npm run build的时候,打包资源的时候
  • how:
"scripts": {
    "build": "webpack"
}

打包资源(css、img、font、其他文件)

  • what: 打包文件资源
  • who: loader模块
  • when: 在webpack执行文件webpack.config.js中配置,打包资源的时候
  • how:
module: {
     rules: [
             {
               test: /\.css$/, // 加载样式,嵌入html页面中
               use: [
                 'style-loader',
                 'css-loader'
               ]
             },
             {
              test: /\.(png|svg|jpg|gif|jpeg)$/, // 加载图片
              use: [
                'file-loader'
              ]
             },
             {
              test: /\.(woff|woff2|eot|ttf|otf)$/, // 加载字体库
               use: {
                loader: "url-loader",
                options: {
                  limit: 50000
                }
               }
             },
             {
              test: /\.(csv|tsv)$/,// 加载数据 CSV TSV格式
                use: [
                'csv-loader'
              ]
              },
              {
                test: /\.xml$/, // 加载xml格式
                use: [
                'xml-loader'
                ]
              }
      ]
  }

手动配置文件打包

  • what: 手动配置多文件打包
  • who: 在入口文件index.html中写死打包后的文件名
  • when: 在webpack.config.js中配置输出文件,执行打包输出的时候
  • how:
// webpack.config.js
const path = require('path');
module.exports = { // 多个文件同时打包,生成多个对应的包
  entry: {
    app: './src/index.js',
    print: './src/print.js'
  },
  output: {
    filename: '[name].bundle.js', // 这里的name动态的循环遍历entry的名字
    path: path.resolve(__dirname, 'dist')
  }
};
// index.html src根据entry中手动配置
<!doctype html>
<html>
  <head>
    <title>Output Management</title>
    <script src="./print.bundle.js"></script>
  </head>
  <body>
    <script src="./app.bundle.js"></script>
  </body>
</html>

问题来了,手动配置如果entry中文件配置名发生变化或删掉多个入口,index.html内script还有跟着改,很麻烦啊,下面就要用到插件了

插件打包

  • what: 利用插件进行自动化打包输出文件
  • who: 插件HtmlWebpackPlugin覆盖原文件,另一个插件CleanWebpackPlugin删除dist文件
  • when: npm run build打包的时候,执行对应的插件
  • how:
  plugins: [
    new CleanWebpackPlugin(),// 最新写法
    new HtmlWebpackPlugin({ // 动态生成index.html覆盖原来的index.html
      title: 'Output Management from dragon'
    })
  ]

热加载HMR

  • what: 代码改动,动态局部加载 HMR(模块热替换)
  • who: webpack自带的插件HotModuleReplacementPlugin、NamedModulesPlugin
  • when: npm run dev的时候,启动本地开发服务
  • how: 安装对应的插件然后引入
    new webpack.NamedModulesPlugin(), // webpack自带的插件 以便查看修补patch依赖
    new webpack.HotModuleReplacementPlugin()

环境分离与合并

  • what: 为了便于维护,分离不同的环境开发环境和生产环境以及公用的部分,然后利用模块webpack-merge打包
  • who: webpack-merge模块做个环境的合并
  • when: 当运行不同的脚本时,npm run dev、npm run build
  • how: 安装对应的插件然后引入
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack');
module.exports = merge(common, {
     devtool: 'inline-source-map',
     devServer: {
       contentBase: './dist',
       hot: true
     },
     plugins: [
      new webpack.NamedModulesPlugin(), // webpack自带的插件 以便查看修补patch依赖
      new webpack.HotModuleReplacementPlugin()
    ]
});

拆分代码打包

  • what: 重复引用包或重复代码时,我们就要分开打包减少包的体积,提高构建效率
  • who: webpack4.0以后自带配置optimization
  • when: npm run build的时候
  • how: 在webpack.config下配置参数即可
   optimization: { // 拆分代码 提取公用的引用包
    splitChunks: {
      cacheGroups: {
        commons: {
          name: 'commons',
          chunks: 'initial', // initial初始块 async按需加载 all所有
          minChunks: 1 // 引用的最小个数
        }
      }
    }
  }

总结

以上是本文的实战部分,每部分都有一个完整的可运行的项目,自行动手效果会更好些。

下一节,将谈谈webpack性能优化的部分,以及开发一个给予多技术栈的脚手架。

通过上面的介绍,希望给你一些建设性的参考,有任何问题欢迎骚扰,加入【前端突击】,长按二维码关注,或微信搜索 前端突击 一起探讨前端的边界

欢迎关注,【前端突击】猎鹰突击,迎难而上,期待你的加入...