【博学谷学习记录】超强总结,用心分享 | webpack基础篇

101 阅读6分钟

webpack是什么

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

webpack的作用

  • 重新加载编译,将浏览器不认识的语法编译成浏览器认识的语法。less编译成css,ES6语法转换成ES5。
  • 减少io请求。发送请求时,会发送一个html到浏览器,这时,打开控制台会发现html页面通过script、link等标签引用的静态,浏览器会再次发出请求去获取这些资源。如何webpack打包,将所有的静态资源都合并好了,减少了io请求。

webpack的安装

webpack的运行是依赖Node环境的,所以我们需要先安装node.js长期支持版本。

  • 全局安装webpack npm i webpack webpack-cli -g
  • 项目中安装webpack npm i webpack webpack-cli -D

webpack的使用

1.webpack-cli

npm 5.2以上的版本提供了一个 npx 命令。
npx 想要解决的主要问题,就是调用项目内部安装的模块,原理就是在 node_modules 下的 .bin 目录中找到对应的命令执行。
使用 webpack 命令:npx webpack

2.webpack的配置

首先我们需要了解一下webpack的四大核心概念

  • 入口(entry):程序的入口js
  • 出口(output):打包后存放的位置
  • loader:用于对模块的源代码进行转换
  • 插件(plugins):插件的目的在于解决loader无法实现的其他事 webpack 4.0 之后可以实现 0 配置打包构建,但是 0 配置的特点就是限制较多,无法自定义配置。
    开发中常用的还是使用webpack配置进行打包构建。
  1. 配置 webpack.config.js
  2. 运行 npx webpack
const path = require('path')

module.exports = {
    // 入口文件配置
    entry: './src/index.js',
    // 出口文件配置
    output: {
        // 输出的路径,webpack2起就规定必须是绝对路径
        path: path.join(__dirname, 'dist'),
        // 输出文件名字
        filename: 'bundle.js'
    }
    mode: 'development'
}

npx webpack 命令配置到 package.json 的脚本中

  1. 配置 package.json
  2. 运行 npm run build
{
    "name": "webpack",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "license": "ISC"
    "scripts": {
        "build": "webpack"
    },
    "devDependencies": {
        "webpack": "^5.73.0",
        "webpack-cli": "^4.10.0"
    }
}

2.1 入口(entry)

入口是指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack会找出有哪些模块和库是入口起点(直接和间接)依赖的。
默认值为 ./src

单个入口语法
module.exports = {
    entry: './src/index.js'
}
对象语法
module.exports = {
    entry: {
        app: './src/app.js'
        vendors: './src/vendors.js'
    }
}
多页面应用程序
module.exports = {
    entry: {
        home: './src/home/index.js'
        news: './src/news/index.js'
    }
}

在多页应用中,(译注:每当页面跳转时)服务器将为你获取一个新的 HTML 文档。页面重新加载新文档,并且资源被重新下载。然而,这给了我们特殊的机会去做很多事:

  • 使用 CommonsChunkPlugin 为每个页面间的应用程序共享代码创建 bundle。由于入口起点增多,多页应用能够复用入口起点之间的大量代码/模块,从而可以极大地从这些技术中受益。

2.2 出口(output)

在 webpack 中配置 output 属性的最低要求是,将它的值设置为一个对象,包括以下两点:

  • filename 用于输出文件的文件名。
  • 目标输出目录 path 的绝对路径。
const path = require('path')

module.exports = {
    output: {
        filename: 'bundle.js',
        path: path.join(__dirname, 'dist'),
    }
}

如果配置创建了多个单独的 "chunk"(例如,使用多个入口起点或使用像 CommonsChunkPlugin 这样的插件),则应该使用占位符(substitutions)来确保每个文件具有唯一的名称。

const path = require('path')

module.exports = {
    entry: {
        app: './src/app.js',
        search: './src/search.js'
    },
    output: {
        filename: '[name].js',
        path: path.join(__dirname, 'dist'),
    }
}

// 写入到硬盘:./dist/app.js, ./dist/search.js

2.3 模式(mode)

只在配置中提供 mode 选项:

module.exports = {
  mode: 'production'
};

或者从 CLI 参数中传递:

webpack --mode=production

支持以下字符串值:

  • development 会将 process.env.NODE_ENV 的值设为 development
    启用 NamedChunksPlugin 和 NamedModulesPlugin
    development 打包后,一些没有依赖的方法 变量 文件会保留,production 则会移除。
  • production 会将 process.env.NODE_ENV 的值设为 production
    启用 FlagDependencyUsagePluginFlagIncludedChunksPluginModuleConcatenationPlugin
    NoEmitOnErrorsPluginOccurrenceOrderPluginSideEffectsFlagPlugin 和 UglifyJsPlugin
    production 打包后,代码会进行压缩,比 development 的文件小。

2.4 loader

loader 用于对模块的源代码进行转换。loader 可以使你在 import 或"加载"模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript,或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS文件!

2.4.1 loader 的使用

在你的应用程序中,有三种使用 loader 的方式:

  • 配置(推荐):在 webpack.config.js 文件中指定 loader。
  • 内联:在每个 import 语句中显式指定 loader。
  • CLI:在 shell 命令中指定它们。
2.4.2 处理 css

安装 loader 所需的依赖 npm i css-loader style-loader -D

module.exports = {
    module: {
        rules: [
            // 配置的是用来解析.css文件的loader(style-loader和css-loader)
            {
                // 用正则匹配当前访问的文件后缀名是 .css
                test: /\.css$/,
                // webpack 底层调用这些包的顺序是从右到左
                use: ['style-loader', 'css-loader']
            }
        ]
    }
}
2.4.3 处理 less 和 sass

安装 npm i less less-loader sass-loader node-sass -D

{test: /\.less$/, use:['style-loader', 'css-loader', 'less-loader']}
{test: /\.s(a|c)ss$/, use:['style-loader', 'css-loader', 'sass-loader']}
2.4.3 处理图片和字体

安装 npm i file-loader url-loader -D
使用 url-loader 需要安装 file-loader

{
    test: /\.(png|jpg|gif|jpeg|bmp)$/, 
    use:[{
        loader: 'url-loader',
        options: {
            // limit 表示如果图片大于5KB, 就以路径形式展示,小于的话就用base64格式展示
            limit: 5 * 1024,
            // 配置输出路径(图片打包后统一放到 根目录下的 images 目录中)
            outputPath: 'images'
            // 配置打包后的图片名称 (原图片-hash:4(前四位hash值).原图片后缀)
            name: '[name]-[hash:4].[ext]'
        }
    }]
}
{test: /\.(woff|woff2|eot|svg|ttf)$/, use: 'url-loader'}
2.4.4 处理 ES6+ 语法

安装 npm i babel-loader @babel/core @babel/preset-env -D
如果需要支持更高级的ES6语法,可以继续安装插件
npm i @babel/plugin-proposal-class-properties -D
也可以根据需求在babel官网找插件进行安装

{
    test: /\.js$/, 
    use: {
        loader: 'babel-loader',
        options: {
            presets: ['@babel/env'],
            // 使用插件
            plugins: ['@babel/plugin-proposal-class-properties']
        },
    },
    // 不打包的路径
    exclude: /node_modules/
}

官方更建议的做法是在项目根目录下新建一个 .babelrc 的babel配置文件

{
    "presets": [
        "@babel/env"
    ],
    "plugins": [
        "@babel/plugin-proposal-class-properties"
    ]
}

2.5 插件(plugins)

插件是 webpack 的支柱功能。webpack 自身也是构建于,你在 webpack 配置中用到的相同的插件系统之上!

插件目的在于解决 loader 无法实现的其他事

2.5.1 plugins 的用法

由于插件可以携带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入 new 实例。

2.5.2 plugins 的配置

我们先安装一个 html 插件,用于打包项目中的 html 文件。

  1. 安装 html-webpack-plugin 插件 npm i html-webpack-plugin -D
  2. webpack.config.js 中的 plugins 节点下配置
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); //访问内置的插件

module.exports = {
    plugins: [
        new webpack.optimize.UglifyJsPlugin(),
        new HtmlWebpackPlugin({
            // 打包后的名字
            filename: 'index.html',
            // 当前项目的html模板
            template: './src/index.html'
        })
    ]
}
2.5.3 常用插件
  • clean-webpack-plugin 该插件可以在 npm run build 时自动清除 dist 目录后重新生成。

安装 npm i clean-webpack-plugin -D

const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
    plugins: [
        new CleanWebpackPlugin()
    ]
}
  • BannerPlugin 这是一个webpack的内置插件,用于给打包的JS文件加上版权注释信息
  1. 引入 webpack 插件
const webpack = require('webpack) 
  1. 创建插件对象
plugins: [
    new webpack.BannerPlugin('博学谷')
]