手把手教你webpack配置,读完马上掌握webpack!

2,753 阅读7分钟

一. 什么是webpack?

本文代码执行环境:node 10 以上,webpack 4 以上

1.概念

webpack 官网

官网的定义:

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

大白话理一下:

1)看看你的项目

  • 有各种各样的文件格式:.vue,.js,.css/less/scss/sass,图片,字体图标……
  • 用到了ES6/7/8 语法 or 特性,以及更高级的语法
  • 体积庞大的node_modules
  • src文件夹下,业务代码文件的数量惊人
  • 开发环境的跨域问题,解决时头发抓到秃
  • 控制台爆红,点击进去后发现和自己写的源代码不一样
  • 开发时,每次修改代码都要手动刷新浏览器,调个样式调到头皮发麻
  • 部署上线时,蹲守公司,王者打到没电,月亮西斜,项目还在打包
  • ...

2)试想一下

  • 这样的数量的文件直接若是上传到服务器,得传多久?

  • 浏览器挨个读取这么多数量的js文件,然后挨个分析,挨个结合这么多数量的css文件,最后组装呈现在用户面前,用户得等多久?

  • ES6/7/8等高级语法浏览器不认识,怎么办?

  • ……

3)然后,你突然发现这些问题webpack都轻松搞定了。如图所示

这张图中,webpack做了大量工作

  • 文件种类多,业务代码复杂,webpack通过分析依赖进行模块合并归类压缩,文件体积变小了
  • 高级/新兴语法,webpack进行代码校验,转译,变成浏览器认识的 js
  • 考虑到速度痛点,webpack在分析依赖的时候使用了高级手段,大大增速
  • node_modules体积庞大,只要你告诉webpack,它就会智能忽略一些你没用到的部分,加快打包速度
  • webpack在打包的时候还进行了代码分割/分离,多模块共享,防止重复分析/加载

针对上边列举的痛点/问题,贴心的webpack同样解决了

  • webpack可以让浏览器自动刷新,而且是局部刷新,让你实时看到代码修改效果
  • 开发环境的跨域问题,跨域通过webpack配置轻松解决
  • SPA应用,通过按需加载,懒加载,代码分割,使用缓存动态打包等,可以大大加快首屏速度,让你的用户小可爱不再久等

通过上边的一堆文字,此时你的心中应该明白了webpack是干什么的,它有什么用。

世上任何概念的定义,都是从其性质,适用范围,作用来下的。

看到这里的你,脑中已经有了webpack的概念吧?

2. 核心组成

  • 入口(Entry)
  • 出口(Output)
  • loaders
  • 插件 (Plugins)
  • mode (模式:开发or生产)
  • Browser Compatibility 浏览器兼容(webpack5.0新增)
  • Environment 环境(webpack5.0新增)

开始配置前,你需要在根目录创建一个 webpack.config.js 文件

2.1 入口与出口

这两个的配置只需要注意两点:出入口数量对应,出入口的路径

数量一致:一入口 VS 一出口,多入口vs 多出口

出入口路径:入口:相对路径;出口:绝对路径

为保证路径准确,需要用到node内置的 path模块,直接require即可

//关于path的用法,小可爱们自行百度
const path = require('path')

// webpack的配置文件遵循着CommonJS规范。什么是ommonJS规范?小可爱们自行百度
module.exports = {
    entry: './src/main.js',
    output: {
        // path.resolve() : 该方法解析当前相对路径的绝对路径
        // path.join():用于路径拼接
        // output 必须是绝对路径,否则报错
        // 方法一:path: path.resolve(__dirname, './dist/'),
        // 方法二:path: path.join(__dirname, './dist/'),
        filename: 'bundle.js' //指定打包后的文件名
    },
}

2.2 loaders

webpack默认只处理js文件,其他非js文件,就需要loaders出马

(1)注意loaders的执行顺序:从下到上,从右到左

在平时配置的时候要在查清楚各个loaders的使用前后规则,否则会报错

(2)可以手动干预它们的执行顺序吗?

可以,在use后再加个enforce属性进行配置即可

enforce 可选值:pre:提前;post:后置

(3)webpack 所有类型loaders的执行顺序:pre > inline > normal > post

inline 指的是在模块中使用import等语法导入,进行单独处理的情况,具体小可爱们自行查看官网/百度

(4)通用的配置

无高级语法的情况下

loaders在webpack的低版本中的写法与现在不同,4,5版本的写法一致,记住以下写法即可

module 与出入口平级:

module : [ rules : [ {test:// , use:[]/''} ]

下面的代码中url-loader用于处理,归类图片,打包后项目中的图片都会集中放在配置的文件夹下,这里体现了webpack的压缩,归类功能

一定要记住!!!

  • 先npm装一下包,然后再配置

  • 配置exclude: /node_modules/忽略该文件夹的解析,校验和转译,配置后将大大加快打包速度!


module.exports = {

    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, './dist/'),
        filename: 'bundle.js' //指定打包后的文件名
    },
        
     module: {
            rules: [
    
              {
                    test: /\.css$/,
                    use: ['style-loader', 'css-loader']
                },
                {
                    test: /\.less$/,
                    use: ['style-loader', 'css-loader', 'less-loader']
                },
                {
                    test: /\.s(a|c)ss$/,
                    use: ['style-loader', 'css-loader', 'sass-loader']
                },
                // url-loader 基于file-loader 两个功能差不多,只是url-loader 比后者多了些可设置的options
                {
                    test: /\.(jpg|jpeg|png|bmp|gif)$/,
                    use: {
                        loader: 'url-loader',
                        options: {
                            limit: 5 * 1024, //此大小范围内的图片转换成base64,节省请求开销
                            outputPath: 'images', //dist下创建images文件夹,统一放图片
                            name: '[name]-[hash:4].[ext]' // 图片文件名+hash值取4位数,ext:原后缀名
                        }
                    }
                },
                {
                    test: /\.(woff|woff2|eot|svg|ttf)$/,
                    use: 'url-loader'
                },
                {
                    test: /\.js$/,
                    use: {
                        loader: 'babel-loader',
                        // options: {
                        //   presets: ['@babel/env'],
                        //   plugins: [
                        //     '@babel/plugin-proposal-class-properties',
                        //     '@babel/plugin-transform-runtime'
                        //   ]
                        // }
                    },
                    exclude: /node_modules/,
                }
            ]
        },
    }

(5)不可忽视的 babel

高级语法的情况下

babel 的主要作用用于转译,将高级语法转换成浏览器识别的语法

随着项目的不断扩大,你会发现你不知不觉中用了很多 babel 家族的loader和插件,这个时候官方建议我们在根目录下创建一个.babelrc文件,专门用来配置babel 家族

有个特别需要注意的点:

配置完babel-loader后,项目可以转换ES6诸如class定义类这样的语法,但是原型新增的方法[].inculdes()这种,babel 默认是无法转换的,需要装一个补丁polyfill

npm i @babel/polyfill -S

在入口处配置

entry: ['@babel/polyfill', './src/main.js'],

或者,在使用新方法的地方引入:

import '@babel/polyfill'

webpack 官方说5.x以后将取消这个补丁,粗略看了一下更新好像没有移除,辛苦小可爱们给我科普一下,这个补丁后来怎么样了

2.3 插件 (Plugins)

loader做不到的事,插件做!

步骤:

  • npm装包
  • webapck官网查看你装的包怎么配置

这一块,实在不知不知道还要讲啥,就上图示范一下配置位置吧

plugins 与出入口平级

const path = require('path')

module.exports = {

    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, './dist/'),
        filename: 'bundle.js' //指定打包后的文件名
    },
        
     module: {
            rules: [
              {
                    test: /\.css$/,
                    use: ['style-loader', 'css-loader']
                },
                {
                    test: /\.less$/,
                    use: ['style-loader', 'css-loader', 'less-loader']
                },
                {
                    test: /\.s(a|c)ss$/,
                    use: ['style-loader', 'css-loader', 'sass-loader']
                },
                // url-loader 基于file-loader 两个功能差不多,只是url-loader 比后者多了些可设置的options
                {
                    test: /\.(jpg|jpeg|png|bmp|gif)$/,
                    use: {
                        loader: 'url-loader',
                        options: {
                            limit: 5 * 1024, //此大小范围内的图片转换成base64,节省请求开销
                            outputPath: 'images', //dist下创建images文件夹,统一放图片
                            name: '[name]-[hash:4].[ext]' // 图片文件名+hash值取4位数,ext:原后缀名
                        }
                    }
                },
                {
                    test: /\.(woff|woff2|eot|svg|ttf)$/,
                    use: 'url-loader'
                },
                {
                    test: /\.js$/,
                    use: {
                        loader: 'babel-loader',
                        // options: {
                        //   presets: ['@babel/env'],
                        //   plugins: [
                        //     '@babel/plugin-proposal-class-properties',
                        //     '@babel/plugin-transform-runtime'
                        //   ]
                        // }
                    },
                    exclude: /node_modules/,
                }
            ]
        },
        plugins: [
        //以下插件是举例:
        new CleanWebpackPlugin(),
        new CopyWebpackPlugin([{
            from: path.join(__dirname, 'assets'),
            to: 'assets'
        }]),
    ],
    }

特意将整段代码贴上,让小可爱们有个直观的认识。

二. webpack高级配置(性能优化方向)

其实就是各种loader和插件的组合

我太饿了 ,我先去吃饭了,后续补充