从0-1 webpack 手动搭建项目
1. 安装 npm 包
npm install webpack-cli webpack -D
2. 在指定文件夹下面创建配置文件
我们可以在根目录,或者自己想放的目录(eg: /config)下,创建对应的配置文件
我们可以写三个配置文件以便区分环境等
# at /config
touch webpack.common.js
touch webpack.dev.js
touch webpack.prod.js
复制代码
2.5 全部进行es module 配置(非必须,可选)
在package.json
中配置属性type
的值为module
,来指定所有的js
文件都用es module
进行解析。
# package.json
{
"type": "module"
}
复制代码
这里要注意,如果我们使用es module
的话, 是不支持__dirname
、__filename
的。 我们查找文件定义时的地址,可以直接用import.meta.url
(为当前文件的地址),并用 url
模块中的URL来生拼接成想要的内容,而不用再使用__dirname
、__filename
等 例如:
import { URL } from 'url'
export default {
entry: {
// index: path.join(__dirname, "../src/index.js")
index: new URL('../src/index.js', import.meta.url).pathname,
},
output: {
filename: '[name].[contenthash:4].js',
// path: path.join(__dirname, '../dist') // distribution 发行版
path: new URL('../dist/', import.meta.url).pathname,
}
}
复制代码
3. 配置scripts相关包
在配置完后由于我们要合并配置文件夹,同时可能项目需要在不同平台上启动,我们可以安装下面两个工具包
npm install webpack-merge cross-env -D
复制代码
webpack-merge
是用来合并配置文件
cross-env
用来处理命令行中的不同平台系统的兼容问题
4. 使用配置内容生成HTML文件
先安装html-webpack-plugin
来处理生成 html
文件
npm install html-webpack-plugin -D
同时为了开发调试能自动启动服务器,我们可以使用
npm install webpack-dev-server -D
来处理本地服务的问题
5. 支持前端框架,react为例
先引用包
npm install react react-dom -S
配置编译工具
npm install babel-loader @babel/core @babel/preset-react -D
// .babelrc 文件
{
"presets": ["@babel/preset-react"] // preset 是官方配置好的plugins集合,另外配置了一些options
}
复制代码
// webpack.common.js 配置文件
module: {
rules: [
{
test: /\.(js|jsx)$/,
loader: 'babel-loader'
}
]
}
复制代码
6. 支持ts
npm i @babel/preset-typescript -D
// .babelrc 文件
{
"presets": ["@babel/preset-react", "@babel/preset-typescript"]// preset 是官方配置好的plugins集合,另外配置了一些options
}
复制代码
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/, // 增加ts类型支持
loader: 'babel-loader'
}
]
}
复制代码
7. 支持css和预处理器
npm i style-loader css-loader sass sass-loader less less-loader
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
loader: 'babel-loader'
},
{
test: /\.css$/,
use:['style-loader','css-loader']
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'],
{
test: /\.(sass|scss)$/,
use:['style-loader','css-loader', 'sass-loader']
}
]
}
复制代码
在这里要注意如果引入一个loader, 我们直接写 lodader
,如果要引入多个,使用use
, 并且use
数组中的loader的执行顺序是从右到左执行的(类似于每次pop出一个loader执行)。
8.支持img引入等
npm install url-loader file-loader -D
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
loader: 'babel-loader',
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'],
},
{
test: /\.(sass|scss)$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.(png|jpg|gif|jpeg)$/,
use: [{ loader: 'url-loader', options: { limit: +10240 } }],
},
{ test: /\.(woff|woff2|eot|ttf|otf)$/, use: 'file-loader' },
],
}
复制代码
其中 file-loader
和url-loader
的区别
file-loader 用来解析图片和字体
url-loader 也可以用来处理图片和字体,还可以设置较小资源自动 base64
9. 支持 antd
npm install antd -S
如果我们引入了antd/dist/antd.less
会报错误,刚刚不是已经处理过less
的编译了吗?为什么还会报错呢?
先不着急,我们看看报错的说明
这是提示我们在less文件中不支持javascript语法。我们需要在less-loader
中进行配置使其支持js
{
test: /\.less$/,
use: ['style-loader', 'css-loader', {
loader: 'less-loader',
options: {
lessOptions: {
javascriptEnabled: true
}
}
}],
},
复制代码
关于javscriptEnabled disprecated回答
10. 美化:给Terminal
编译过程加个进度条
npm i webpackbar -D
webpackbar是一个plugin, 可以用来显示编译打包进度。
// webpack.dev.config
plugins: [new Webpackbar()],
复制代码
11. 优化
external优化
externals
配置选项提供了「从输出的 bundle 中排除依赖」的方法。相反,所创建的 bundle 依赖于那些存在于用户环境(consumer's environment)中的依赖。此功能通常对 library 开发人员来说是最有用的,然而也会有各种各样的应用程序用到它。
external 能防止将某些 import
的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。
我们可以从CDN引入react
,react-dom
,而不是打包。
externals: {
// 外部扩展
react: 'React',
'react-dom': 'ReactDOM',
},
复制代码
这样可以很好地优化打包的时间
stats 对象
stats
选项让你更精确地控制 bundle 信息该怎么显示。如果只是想要获取某部分 bundle 的信息,使用 stats 选项是比较好的折衷方式。
stats.modules
: 告知 stats
是否添加关于构建模块的信息。默认为true
TerserWebpackPlugin
该插件使用 terser 来压缩 JavaScript。
webpack v5 开箱即带有最新版本的 terser-webpack-plugin
。如果你使用的是 webpack v5 或更高版本,同时希望自定义配置,那么仍需要安装 terser-webpack-plugin
。如果使用 webpack v4,则必须安装 terser-webpack-plugin
v4 的版本。
npm install terser-webpack-plugin esbuild --save-dev
optimization: {
minimizer: [
new TersetWebpackPlugin({
extractComments:false,
minify: TersetWebpackPlugin.esbuildMinify // esbuild 提速
}),
]
},
复制代码
css-mini-extract-plugin
这个插件将 CSS 提取到单独的文件中。它为每个包含 CSS 的 JS 文件创建一个 CSS 文件。它支持 CSS 和 sourcemap 的按需加载。只在webpack v5及以后版本支持。
npm i mini-css-extract-plugin -D
用法不再赘述,直接看文档
clean-webpack-plugin
A webpack plugin to remove/clean your build folder(s).
const webpackConfig = {
plugins: [
/**
* All files inside webpack's output.path directory will be removed once, but the
* directory itself will not be. If using webpack 4+'s default configuration,
* everything under <PROJECT_DIR>/dist/ will be removed.
* Use cleanOnceBeforeBuildPatterns to override this behavior.
*
* During rebuilds, all webpack assets that are not used anymore
* will be removed automatically.
*
* See `Options and Defaults` for information
*/
new CleanWebpackPlugin(),
],
};
复制代码
npm i clean-webpack-plugin -D
css-minimizer-webpack-plugin
This plugin uses cssnano to optimize and minify your CSS.
npm i css-minimizer-webpack-plugin -D
happyPack
由于 JavaScript 是单线程模型,我们可以通过使用多进程,启用多核 CPU 的能力。happyPack的思想是使用多个子进程去解析和编译JS,css,等,这样就可以并行处理多个子任务,多个子任务完成后,再将结果发到主进程中
npm install happypack -D
1. 创建 happypack 插件实例
// webpack.common.js
// import HappyPack from 'happypack'
// import os from 'os'
// const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length})
plugins: [
new HappyPack({
id: 'babel', // 唯一标识id, 表示当前实例,后面会在 module/rules中进行使用
loaders: ['babel-loader?cacheDirectory'], // 和module/rules中的 Loader用法一致
threads: 3, // 代表开启几个子进程去处理这一类型的文件,默认是3个,类型必须是整数。
threadPool: happyThreadPool, // // 使用共享进程池中的子进程去处理任务
}),
],
复制代码
2. 在 Loder中使用
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/,
// loader: 'babel-loader',
// 在 Loader 配置中,所有文件的处理都交给了 happypack/loader 去处理,使用紧跟其后的 querystring ?id=babel 去告诉 happypack/loader 去选择哪个 HappyPack 实例去处理文件。
use: ['happypack/loader?id=babel'],
exclude: /node_modules/,
},
]
},
}
复制代码
-
TODO: 后续补充更新,欢迎留言发问,催更
eslint
CI/CD
pre commit 检查