webpack模块化原理

139 阅读3分钟

## webpack配置

// ./webpack.config.jsconst webpack = require("webpack");const HtmlWebpackPlugin = require("html-webpack-plugin");const TerserWebpackPlugin = require("terser-webpack-plugin");const MiniCssExtractPlugin = require("mini-css-extract-plugin");const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");module.exports = {    //入口    entry: {        index: "./src/index.js",        album: "./src/album.js",    },    //输出    output: {        filename: "[name].bundle.js", // [name] 是入口名称    },    //工作模式    mode: "development",    //Loader编译特殊资源    module: {        rules: [            {                test: /\.css$/,                use: [                    // 'style-loader', // 将样式通过 style 标签注入                    MiniCssExtractPlugin.loader,                    "css-loader",                ],            },        ],    },    // source map 设置    devtool: "source-map",    // 详细配置文档:https://webpack.js.org/configuration/dev-server/    devServer: {        contentBase: ["public", path.join(__dirname, "dist")], //静态资源访问        compress: true,        port: 9000,        hot: true,        hotOnly: true,        proxy: {            "/api": {                target: "https://api.github.com",                pathRewrite: {                    "^/api": "", // 替换掉代理地址中的 /api                },                changeOrigin: true, // 确保请求 GitHub 的主机名就是:api.github.com            },        },    },    //Plugin插件扩展webpack功能    plugins: [        new webpack.DefinePlugin({            //Define Plugin            API_BASE_URL: JSON.stringify("https://api.example.com"),        }),        new MiniCssExtractPlugin(),        new webpack.HotModuleReplacementPlugin(),        new HtmlWebpackPlugin({            title: "Multi Entry",            template: "./src/index.html",            filename: "index.html",            chunks: ["index"], // 指定使用 index.bundle.js        }),        new HtmlWebpackPlugin({            title: "Multi Entry",            template: "./src/album.html",            filename: "album.html",            chunks: ["album"], // 指定使用 album.bundle.js        }),    ],    optimization: {        minimizer: [            new TerserWebpackPlugin(),            new OptimizeCssAssetsWebpackPlugin(),        ],        splitChunks: {            // 自动提取所有公共模块到单独 bundle            chunks: "all",        },        // 模块只导出被使用的成员        usedExports: true,        // 尽可能合并每一个模块到一个函数中        concatenateModules: true,        // 压缩输出结果        minimize: true,        //是否移除副作用模块代码, 最好的办法就是在 package.json 中的 sideEffects 字段中标识需要保留副作用的模块路径(可以使用通配符)        sideEffects: true,    },};

## 初始化

npm init --yesnpm webpack webpack-cli -S

·

基本入口输出配置

· entry

· output

·

工作模式

: mode

· none

模式下,运行最原始的打包,不做任何额外处理。

· development

模式下,自动优化打包速度,添加一些调试过程中的辅助插件;

· production

模式下,启动内置优化插件,自动优化打包结果,打包速度偏慢;

· Loader

· Loader

机制是

Webpack

最核心的机制,因为正是有了

Loader

机制,

Webpack

才能足以支撑整个前端项目模块化的大梁,实现通过

Webpack

去加载任何你想要加载的资源。

· Webpack Loader: module

· rules:[]

· test

·

正则表达式,用来匹配打包过程中所遇到文件路径

: /\.css$/

· use

·

它用来指定匹配到的文件需要使用的

loader

·

常用

loader

·

名称

链接

file-loader webpack.js.org/loaders/fil… webpack.js.org/loaders/url… webpack.js.org/loaders/bab… webpack.js.org/loaders/sty… webpack.js.org/loaders/css… webpack.js.org/loaders/sas… webpack.js.org/loaders/pos… github.com/webpack-con… github.com/vuejs/vue-l…

·

多个

Loader

的配合

·

use

属性修改为一个数组,以便依次使用多个

Loader

。不过同样需要注意,这里的执行顺序是从后往前,也就是说我们应该把先执行的

css-loader

放在后面,

style-loader

放在前面。

· Webpack

加载资源文件的过程类似于一个工作管道,你可以在这个过程中依次使用多个

Loader

,但是最终这个管道结束过后的结果必须是一段标准的

JS

代码字符串。

· Plugin

·

核心

:

钩子机制

·

插件都是通过往

Webpack

生命周期的钩子中挂载任务函数实现的。

Webpack

整个工作过程会有很多环节,为了便于插件的扩展,

Webpack

几乎在每一个环节都埋下了一个钩子。这样我们在开发插件的时候,通过往这些不同节点上挂载不同的任务,就可以轻松扩展

Webpack

的能力。

·

常见场景

·

实现自动在打包之前清除

dist

目录(上次的打包结果);

·

自动生成应用所需要的

HTML

文件;

·

根据不同环境为代码注入类似

API

地址这种可能变化的部分;

·

拷贝不需要参与打包的资源文件到输出目录;

·

压缩

Webpack

打包完成后输出的文件;

·

自动发布打包结果到服务器实现自动部署。

·

面向切面编程

· AOP

全称

Aspect Oriented Programming

意为面向切面编程,也叫做面向方法编程,是通过预编译方式和运行期动态代理的方式实现不修改源代码的情况下给程序动态统一添加功能的技术。

· DevServer
webpack-dev-server:#

安装

webpack-dev-server$

npm install webpack-dev-server --save-dev#

运行

webpack-dev-server$

npx webpack-dev-serve

·

端口

·

静态资源访问

· Proxy

代理

-

解决跨域问题

· Devtool

开发辅助工具

: Source Map

· devtool: 'source-map' // source map

设置

·

模块支持热替换(

HMR

·

魔法注释

· //

魔法注释

import( /* webpackChunkName: 'posts' */ './posts/posts').then(({default: posts}) => {mainElement.appendChild(posts())});

·

让配置文件支持智能提示

需要注意的是:我们添加的

import

语句只是为了导入

Webpack

配置对象的类型,这样做的目的是为了标注

config

对象的类型,从而实现智能提示。

在配置完成后一定要记得注释掉这段辅助代码

,因为在

Node.js

环境中默认还不支持

import

语句,如果执行这段代码会出现错误。

·

通过

import

的方式导入

Webpack

模块中的

Configuration

类型,然后根据类型注释的方式将变量标注为这个类型。

// ./webpack.config.js
import { Configuration } from 'webpack'
/**
* @type {Configuration}
*/
const config = {
entry: './src/index.js',
output: {
filename: 'bundle.js'
}
}
module.exports = config