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;
}
相关推荐
桂月二二4 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062065 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb5 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角5 小时前
CSS 颜色
前端·css
九酒6 小时前
从UI稿到代码优化,看Trae AI 编辑器如何帮助开发者提效
前端·trae
浪浪山小白兔7 小时前
HTML5 新表单属性详解
前端·html·html5
lee5767 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579657 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me8 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架
浏览器爱好者8 小时前
如何构建一个简单的React应用?
前端·react.js·前端框架