webpack is a module bundler.
webpack 是一个模块打包器,它的主要目标是将 JavaScript 文件打包在一起,打包后的文件用于在浏览器中使用,但它也能够胜任转换(transform)、打包(bundle)或包裹(package)任何资源(resource or asset)。
1.node环境
2.全局安装webpack
npm install webpack webpack-cli -g
webpack -v
全局安装会导致不同webpack版本无法同时启动
3.项目内安装webpack
npm install webpack webpack-cli --save--dev
# === npm install webpack webpack-cli -D
用法:npx + 调用的命令
当我们全局和局部项目都安装了webpack时
npx webpack // 会在当前项目的node_modules中寻找.bin/webpack
webpack // 会调用全局的webpack
npm 从5.2版开始,增加了 npx 命令。
npx 想要解决的主要问题,就是调用项目内部安装的模块。
npx 的原理很简单,就是运行的时候,会到node_modules/.bin
路径和环境变量$PATH
里面,检查命令是否存在。
由于 npx 会检查环境变量$PATH
,所以系统命令也可以调用。
# 等同于 ls
$ npx ls
摘自阮一峰的网络日志
在package.json文件中配置script,这样我们运行npm run bundle
,就会在当前项目寻找webpack命令
{
"name": "webpack-demo",
"scripts": {
"bundle": "webpack"
},
"devDependencies": {
"webpack": "^5.14.0",
"webpack-cli": "^4.3.1"
}
}
npm run bundle
# 相当于 npx webpack
webpack默认配置文件名:webpack.config.js
指定配置文件打包
npx webpack --config webpack.my.config.js
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist')
}
};
webpack 可以使用 loader 来预处理文件。这允许你打包除 JavaScript 之外的任何静态资源。你可以使用 Node.js 来很简单地编写自己的 loader。
file-loader
将文件发送到输出文件夹,并返回(相对)URL
npm install file-loader -D
webpack module配置
module.exports = {
mode: 'development',
entry: './src/index.js',
module: {
rules: [
{
test: /\.jpg$/, use: {
loader: 'file-loader' } }
]
}
};
将文件发送到输出文件夹,并返回(相对)URL
webpack v4文档,file-loader options
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(jpg|png|gif)$/,
use: {
loader: 'file-loader',
options: {
// placeholder 占位符
name: '[name]_[hash].[ext]',
outputPath: 'images/'
}
}
}
]
}
};
在浏览器中使用
import avatar from './images/avatar.jpg';
const img = new Image();
img.src = avatar;
let root = document.getElementById('root');
root.appendChild(img);
webpack v4文档,url-loader
像 file loader 一样工作,但如果文件小于限制,可以返回 data URL;图片大于limit,会生成对应文件。
npm install url-loader -D
module: {
rules: [
{
test: /\.jpg$/,
use: {
loader: 'url-loader',
options: {
// placeholder 占位符
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 2048
}
}
}
]
}
style-loader
将模块的导出作为样式添加到 DOM 中
css-loader
解析 CSS 文件后,使用 import 加载,并且返回 CSS 代码
npm install style-loader css-loader -D
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
打包成功会在head标签中插入style标签
sass-loader
加载和转译 SASS/SCSS 文件
安装
npm install sass-loader node-sass --save-dev
module: {
rules: [
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
]
}
当我们打包一个scss文件时,loader是按照从后往前执行,先sass-loader,再css-loader,最后style-loader
PostCSS 利用 JavaScript 的强大编程能力对 CSS 代码进行转换。数以百计的 PostCSS 插件可以用来为 CSS 属性添加特定于浏览器厂商的前缀、支持未来 CSS 语法、模块化、代码检测等。
npm install postcss-loader autoprefixer -D
在项目根目录新建 postcss.config.js,配置使用的插件
module.exports = {
plugins: [require('autoprefixer')]
};
在打包之后的css自动添加浏览器厂商前缀,如:-webkit-transform
在scss中引入scss时
这种情况会导致新引入的scss不会走之前的loader,我们需要设置importLoaders
importLoaders
,用于配置「css-loader
作用于 @import
的资源之前」有多少个 loader。const path = require('path');
module.exports = {
module: {
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true
}
},
'sass-loader',
'postcss-loader'
]
}
]
}
};
使用file-loader当作静态资源打包
rules: [
{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader'
}
},
]
阅读webpack文档-资源管理
webpack v4 plugin
plugin 可以在webpack运行到某个时刻的时候,自动帮我们做一些事情。
HtmlWebpackPlugin简化了HTML文件的创建,以便为你的webpack包提供服务。这对于在文件名中包含每次会随着编译而发生变化哈希的 webpack bundle 尤其有用。 你可以让插件为你生成一个HTML文件,使用lodash模板提供你自己的模板,或使用你自己的loader。
作用:HtmlWebpackPlugin,会在打包结束后,自动生成一个html文件,并把打包生成的js自动引入到html中
npm install --save--dev html-webpack-plugin
配置
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [new HtmlWebpackPlugin({
template: 'src/index.html' // 设置模板
})]
打包删除上次打包的结果
npm install clean-webpack-plugin -D
配置
const {
CleanWebpackPlugin } = require('clean-webpack-plugin');
plugins: [
new CleanWebpackPlugin()
]
阅读:管理输出
配置多个打包文件
entry: {
a: './src/index.js',
b: './src/index.js'
},
output: {
// 公共路径
publicPath: 'http://cdn.com.cn',
// 输出文件:Template strings占位符
filename: '[name].js',
// 输出路径
path: path.join(__dirname, 'dist')
},
Devtool配置
此选项控制是否生成,以及如何生成 source map。
选择一种 source map 格式来增强调试过程。不同的值会明显影响到构建(build)和重新构建(rebuild)的速度。
sourceMap是一个映射关系
从打包后的文件,找到对应映射的源代码的位置
devtool: 'source-map'
可以生成:bundle.js 和 bundle.js.map
每次修改完文件,我们都需要重新打包,刷新网页,效率低
–watch 检测到打包的文件改变时,自动重新打包
在package.json中添加脚本
"scripts": {
"bundle": "webpack",
"watch": "webpack --watch"
},
提供一个本地开发服务器
通过 webpack-dev-server 的这些配置,能够以多种方式改变其行为。这是一个简单的示例,利用
gzips
压缩dist/
目录当中的所有内容并提供一个本地服务(serve):
安装
npm install webpack-dev-server -D
基本配置
devServer: {
contentBase: './dist',
open: true,
port: 8080
},
发ajax请求时,要求在服务器上,以http协议打开,我们打开本地开发服务器,就可以发请求了
报错可能出现版本冲突,我的版本
{
"webpack": "^4.25.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10"
}
devServer.proxy 文档
vue react脚手架都以此实现
使用后端在 localhost:3000
上,可以使用它来启用代理:
module.exports = {
//...
devServer: {
proxy: {
'/api': 'http://localhost:3000'
}
}
};
现在,对 /api/users
的请求会将请求代理到 http://localhost:3000/api/users
。
如果不希望传递/api
,则需要重写路径:
module.exports = {
//...
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: {
'^/api' : ''}
}
}
}
};
阅读:开发环境
使用时,并没有dist目录,而是放到内存中,提高效率!
场景:我们修改css只会替换css修改的内容,方便调试
const webpack = require('webpack');
// 配置
devServer: {
contentBase: './dist',
hot: true,
hotOnly: true
}
plugins: [
new webpack.HotModuleReplacementPlugin()
]
js手动HMR,accept方法
if (module.hot) {
module.hot.accept('./number', () => {
document.body.removeChild(document.getElementById('number'));
number();
});
}
babel-loader是webpack loader在打包过程中处理
@babel/core是babel核心库
npm install --save-dev babel-loader @babel/core
npm install @babel/preset-env --save-dev
添加webpack配置
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
到此,我们只能处理部分es6语法。但是Promise 数组的 map方法等都不能处理,我们还需要**@babel/polyfill**
通过 Polyfill 方式在目标环境中添加缺失的特性 (通过 @babel/polyfill 模块)
npm install --save @babel/polyfill
在index.js中引入
import '@babel/polyfill';
useBuiltIns
配置低版本的特性按需引入
target
设置目标浏览器,判断是否需要引入低版本不支持的特性,从而减少体积
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
targets: {
edge: '17',
firefox: '60',
chrome: '67',
safari: '11.1'
}
}
]
]
}