webpack

一.webpack基础

1.简单配置

1.1 安装依赖

javascript 复制代码
$ npm install webpack webpack-cli -D # 安装到本地依赖

1.2 工作模式

webpack4之后支持0配置打包

webpack提供了三种模式:

  • development,开发模式,打包更加快速,省了代码优化步骤
  • production,生产模式,打包比较慢,会开启 tree-shaking 和 压缩代码
  • none,不使用任何默认优化选项

如何配置:

javascript 复制代码
module.exports = {
  mode: 'development',
};

1.3 配置文件

虽然webpack之后支持0配置打包,但是实际项目中我们通常需要通过配置文件来打包,以便满足不同的需求。

javascript 复制代码
const path = require('path')

module.exports = {
  mode: 'development', // 模式
  entry: './src/index.js', // 打包入口地址
  output: {
    filename: 'bundle.js', // 输出文件名
    path: path.join(__dirname, 'dist') // 输出文件目录
  }
}

1.4 Loader

Loader的作用是将webpack不认识的内容转换为认识的内容。以下是一些常用loader,

1.4.1 style-loader、css-loader、sass-loader

用途:

  • style-loader 用于将css编译完成的样式,挂载到页面style标签上。
  • css-loader 用于识别.css文件, 处理css必须配合style-loader共同使用,只安装css-loader样式不会生效。
  • sass-loader,将sass语言转换成css语言。

配置:

javascript 复制代码
module.exports = {
    module: {
        rules: [
            {
                test: /\.scss$/,
                use: [
                    "style-loader",
                    "css-loader",
                    "sass-loader"
                ],
                include: /src/, 
            },
        ]
    }
}
1.4.2 postcss-loader

**用途:**用于补充css样式各种浏览器内核前缀

配置:

方式一:在webpack.config.js中配置

javascript 复制代码
{
  test: /\.css$/,
  use: [
    'style-loader',
    'css-loader',
    {
      loader: 'postcss-loader',
      options: {
        plugins: [
          require('autoprefixer')
        ]
      }
    }
  ]
}

方式二:在根目录创建 postcss.config.js

javascript 复制代码
module.exports = {
  plugins: [
    require("autoprefixer")({
      //兼容浏览器的最近两个版本
      //兼容市场占有率大于1%的浏览器(世界的)
      overrideBrowserslist: ["last 2 versions", ">1%"],
    }),
  ],
};
1.4.3 babel-loader

**用途:**将Es6+ 语法转换为Es5语法。

安装:

javascript 复制代码
cnpm i babel-loader @babel/core @babel/preset-env -D
  • babel-loader 这是使babel和webpack协同工作的模块
  • @bable/core 这是babel编译器核心模块
  • @babel/preset-env 这是babel官方推荐的预置器,可根据用户的环境自动添加所需的插件和补丁来编译Es6代码

配置:

javascript 复制代码
module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: "babel-loader",
                    options: {
                        presets: [
                            ['@babel/preset-env', { targets: "defaults"}]
                        ]
                    }
                }
            },
        ]
    }
}
1.4.4 ts-loader

**用途:**用于配置项目typescript

安装:

javascript 复制代码
cnpm i ts-loader typescript -D

配置:

tsconfig.json

javascript 复制代码
{
    "compilerOptions": {
      "declaration": true,
      "declarationMap": true, // 开启map文件调试使用
      "sourceMap": true,
      "target": "es5", // 转换为Es5语法
    }
}  

webpack.config.js

javascript 复制代码
module.exports = {
    entry: "./src/index.ts",
    output: {
        path: __dirname + "/dist",
        filename: "index.js",
    },
    module: {
        rules: [
            {
                {
                	test: /\.ts$/,
                	use: "ts-loader",
            	}
            }
        ]
    }
}
1.4.5 file-loader

用途: 用于处理文件类型资源,如**jpg** ,png 等图片。返回值为**publicPath**为准。

安装:

javascript 复制代码
cnpm i file-loader -D

配置:

javascript 复制代码
module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|jpg|jpeg)$/,
                use: [
                    {
                        loader: "file-loader",
                        options: {
                            name: "[name]_[hash:8].[ext]",
                            publicPath: "https://www.baidu.com" //路径前缀
                        }
                    }
                ]
            }
        ]
    }
}
1.4.6 url-loader

用途:url-loader 也是处理图片类型资源,只不过它与**file-loader** 有一点不同,url-loader 可以设置一个根据图片大小进行不同的操作,如果该图片大小大于指定的大小,则将图片进行打包资源,否则将图片转换为base64字符串合并到js文件里

安装:

javascript 复制代码
cnpm i url-loader -D

配置:

javascript 复制代码
module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|jpg|jpeg)$/,
                use: [
                    {
                        loader: "url-loader",
                        options: {
                            name: "[name]_[hash:8].[ext]",
                            limit: 10240, // 这里单位为(b) 10240 => 10kb
                            // 这里如果小于10kb则转换为base64打包进js文件,如果大于10kb则打包到dist目录
                        }
                    }
                ]
            }
        ]
    }
}
1.4.7 eslint-loader

**用途:**用于检查代码是否符合规范,是否存在语法错误。

安装:

javascript 复制代码
cnpm i eslint-loader eslint -D

配置:

.eslintrc.js

javascript 复制代码
module.exports = {
    root: true,   
    env: {
        browser: true,
    },
    rules: {
        "no-alert": 0, // 禁止使用alert
        "indent": [2, 4], // 缩进风格
        "no-unused-vars": "error" // 变量声明必须使用
    }
}

webpack.config.js

javascript 复制代码
module.exports = {
    module: {
        rules: [
            {
                test: /\.ts$/,
                use: ["eslint-loader", "ts-loader"],
                enforce: "pre",
                exclude: /node_modules/
            },
            {
                test: /\.ts$/,
                use: "ts-loader",
                exclude: /node_modules/
            }
        ]
    }
}

1.5 插件(plugin)

与 Loader 用于转换特定类型的文件不同,插件(Plugin)可以贯穿 Webpack 打包的生命周期,执行不同的任务

1.5.1 HotModuleReplacementPlugin

作用: 模块热更新插件Hot-Module-Replacement 的热更新是依赖于 webpack-dev-server,后者是在打包文件改变时更新打包文件或者 reload 刷新整个页面,HRM 是只更新修改的部分。

配置:

javascript 复制代码
const webpack = require('webpack')

plugins: [
  new webpack.HotModuleReplacementPlugin(), // 热更新插件
]
1.5.2 html-webpack-plugin

作用: 生成 html 文件 。将 webpack 中entry配置的相关入口 chunkextract-text-webpack-plugin抽取的 css 样式 插入到该插件提供的template或者templateContent配置项指定的内容基础上生成一个 html 文件,具体插入方式是将样式link插入到head元素中,script插入到head或者body中。

配置:

javascript 复制代码
const HtmlWebpackPlugin = require('html-webpack-plugin')

plugins: [
  new HtmlWebpackPlugin({
    filename: 'index.html',
    template: path.join(__dirname, '/index.html'),
    minify: {
      // 压缩HTML文件
      removeComments: true, // 移除HTML中的注释
      collapseWhitespace: true, // 删除空白符与换行符
      minifyCSS: true, // 压缩内联css
    },
    inject: true,
  }),
]

inject 有四个选项值

  • true:默认值,script 标签位于 html 文件的 body 底部
  • body:script 标签位于 html 文件的 body 底部(同 true)
  • head:script 标签位于 head 标签内
  • false:不插入生成的 js 文件,只是单纯的生成一个 html 文件
1.5.3clean-webpack-plugin

作用: clean-webpack-plugin 用于在打包前清理上一次项目生成的 bundle 文件,它会根据 output.path 自动清理文件夹;这个插件在生产环境用的频率非常高,因为生产环境经常会通过 hash 生成很多 bundle 文件,如果不进行清理的话每次都会生成新的,导致文件夹非常庞大。

配置:

javascript 复制代码
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

plugins: [
  new HtmlWebpackPlugin({
    template: path.join(__dirname, '/index.html'),
  }),
  new CleanWebpackPlugin(), // 所要清理的文件夹名称
]
1.5.4extract-text-webpack-plugin

**作用:**将 css 成生文件,而非内联 。该插件的主要是为了抽离 css 样式,防止将样式打包在 js 中引起页面样式加载错乱的现象

配置:

javascript 复制代码
const ExtractTextPlugin = require('extract-text-webpack-plugin')

plugins: [
  // 将css分离到/dist文件夹下的css文件夹中的index.css
  new ExtractTextPlugin('css/index.css'),
]

1.6 区分环境

本地开发和部署线上,通常是有不同的需求

本地环境:

  • 需要更快的构建速度
  • 需要打印 debug 信息
  • 需要 live reload 或 hot reload 功能
  • 需要 sourcemap 方便定位问题
  • ...

生产环境:

  • 需要更小的包体积,代码压缩+tree-shaking
  • 需要进行代码分割
  • 需要压缩图片体积
  • ...

针对不同的需求,首先要做的就是做好环境的区分

1.本地安装 cross-env

javascript 复制代码
npm install cross-env -D

2.配置启动命令

package.json

javascript 复制代码
"scripts": {
    "dev": "cross-env NODE_ENV=dev webpack serve --mode development", 
    "test": "cross-env NODE_ENV=test webpack --mode production",
    "build": "cross-env NODE_ENV=prod webpack --mode production"
  },

3.在 Webpack 配置文件中获取环境变量

javascript 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

console.log('process.env.NODE_ENV=', process.env.NODE_ENV) // 打印环境变量

const config = {
  entry: './src/index.js', // 打包入口地址
  output: {
    filename: 'bundle.js', // 输出文件名
    path: path.join(__dirname, 'dist') // 输出文件目录
  },
  module: { 
    rules: [
      {
        test: /\.css$/, //匹配所有的 css 文件
        use: 'css-loader' // use: 对应的 Loader 名称
      }
    ]
  },
  plugins:[ // 配置插件
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ]
}

module.exports = (env, argv) => {
  console.log('argv.mode=',argv.mode) // 打印 mode(模式) 值
  // 这里可以通过不同的模式修改 config 配置
  return config;
}

1.7 devServer

1.安装webpack-dev-server

javascript 复制代码
npm intall webpack-dev-server

当版本 version >= 4.0.0 时,需要使用 devServer.static 进行配置,不再有 devServer.contentBase 配置项。

2.配置本地服务

javascript 复制代码
// webpack.config.js
const config = {
  // ...
  devServer: {
    contentBase: path.resolve(__dirname, 'public'), // 静态文件目录
    compress: true, //是否启动压缩 gzip
    port: 8080, // 端口号
    // open:true  // 是否自动打开浏览器
  },
 // ...
}
module.exports = (env, argv) => {
  console.log('argv.mode=',argv.mode) // 打印 mode(模式) 值
  // 这里可以通过不同的模式修改 config 配置
  return config;
}

为什么要配置 contentBase ?

因为 webpack 在进行打包的时候,对静态文件的处理,例如图片,都是直接 copy 到 dist 目录下面。但是对于本地开发来说,这个过程太费时,也没有必要,所以在设置 contentBase 之后,就直接到对应的静态目录下面去读取文件,而不需对文件做任何移动,节省了时间和性能开销。

1.8 资源模块的使用

webpack5 新增资源模块(asset module),允许使用资源文件(字体,图标等)而无需配置额外的 loader。

资源模块支持以下四个配置:

  1. asset/resource 将资源分割为单独的文件,并导出 url,类似之前的 file-loader 的功能.
  2. asset/inline 将资源导出为 dataUrl 的形式,类似之前的 url-loader 的小于 limit 参数时功能.
  3. asset/source 将资源导出为源码(source code). 类似的 raw-loader 功能.
  4. asset 会根据文件大小来选择使用哪种类型,当文件小于 8 KB(默认) 的时候会使用 asset/inline,否则会使用 asset/resource

配置文件

javascript 复制代码
// ./src/index.js

const config = {
  // ...
  module: { 
    rules: [
      // ... 
      {
        test: /\.(jpe?g|png|gif)$/i,
        type: 'asset',
        generator: {
          // 输出文件位置以及文件名
          // [ext] 自带 "." 这个与 url-loader 配置不同
          filename: "[name][hash:8][ext]"
        },
        parser: {
          dataUrlCondition: {
            maxSize: 50 * 1024 //超过50kb不转 base64
          }
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
        type: 'asset',
        generator: {
          // 输出文件位置以及文件名
          filename: "[name][hash:8][ext]"
        },
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024 // 超过100kb不转 base64
          }
        }
      },
    ]
  },
  // ...
}

module.exports = (env, argv) => {
  console.log('argv.mode=',argv.mode) // 打印 mode(模式) 值
  // 这里可以通过不同的模式修改 config 配置
  return config;
}
相关推荐
迷雾漫步者1 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-2 小时前
验证码机制
前端·后端
燃先生._.3 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖4 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235244 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240255 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar5 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人5 小时前
前端知识补充—CSS
前端·css
GISer_Jing6 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试