1.完成第一次打包
初始化项目
开始前要保证已经进安装了node且可以正常使用
在项目目录下执行初始化命令
D:\code\study-web>npm init
安装webpack
- 默认安装最新版本
npm install --save-dev webpack-cli webpack
- 安装指定版本
npm install --save-dev webpack-cli@3.3.12 webpack@4.44.1
配置文件
node.js配置
"scripts": {
"webpack": "webpack --config webpack.config.js"
},
- 配置完成后执行npm run webpack 等价于执行npm run webpack --config webpack.config.js
- webpack命令的--config参数指定配置文件为webpack.config.js, 如果不指定定默认值就是webpack.config.js
- 可以根据实际的需要配置多个命令
webpack配置
在项目目录下创建webpack.config.js文件,并写入
// 通过require导入path
const path = require('path');
// 设置需要导出的对象
module.exports = {
mode:'development', //默认为线上模式, 这里指定为开发模式
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
};
在src目录下index.js文件引用很多其他js文件,webpack会递归地构建一个依赖关系图 ,其中包含应用程序需要的每个模块,然后将所有这些模块打包成 bundle.js文件输出到dist目录
- webpack可以打包成多个文件,且名称也可以配置
- 该文件属于nood.js的模块,
- 各项配置具体含义请参考webpack核心概念
编译
通过 npm run webpack 命令进行编译
D:\code\study-web>npm run webpack
> study-web@1.0.0 webpack D:\code\study-web
> webpack --config webpack.config.js
Hash: e25fc83c5954c62acd56
Version: webpack 4.44.1
Time: 82ms
Built at: 2021/11/27 下午6:12:59
Asset Size Chunks Chunk Names
bundle.js 4.5 KiB main [emitted] main
Entrypoint main = bundle.js
[./src/index.js] 65 bytes {main} [built]
[./src/module.js] 47 bytes {main} [built]
2.核心概念
入口(entry)
进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
可以通过中配置 entry 属性,来指定一个入口起点(或多个入口起点)。
单入口
- 方式一:字符串的形式
const config = {
entry: './path/to/my/entry/file.js'
};
- 方式二:对象的形式
const config = {
entry: {
main: './path/to/my/entry/file.js'
}
};
上面这两种写法是等价的,两种方式传递给出口的name都为main
出口(output)
单出口
output: {
path: path.resolve(__dirname, 'dist'),
filename: ' main.js',
}
多出口
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
注意:入口的单双必须配合使用
- 单入口可以对应两种出口模式
- 多入口只能对应多出口的写法
loader
loader可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理
使用loader的三种方式
在你的应用程序中,有三种使用 loader 的方式:
- 配置(推荐):在 webpack.config.js 文件中指定 loader。
- 内联:在每个
import语句中显式指定 loader。 - CLI:在 shell 命令中指定它们。
babel-loader的使用
安装babel
- 默认安装最新版本
npm install --save-dev @babel/core @babel/cli
// 安转指定编译版本的包
npm install @babel/preset-env@ --save-dev
- 安装指定版本
npm install --save-dev @babel/core@7.11.0 @babel/cli@7.10.5
// 安转指定编译版本的包
npm install @babel/preset-env@7.11.0 --save-dev
babel/cli是用于在命令行使用bable的,如何如果将bable作为loader结合webpack使用可以不安装
安装babel-loader
npm install --save-dev babel-loader@8.1.0
配置文件
- 配置babel
在项目目录创建.babelrc文件,写入
{
"presets": ["@babel/preset-env"]
}
- 配置loader
这里采用loader的第一种使用方式:配置webpack.config.js文件
module.rules允许你在 webpack 配置中指定多个 loader。 这是展示 loader 的一种简明方式,并且有助于使代码变得简洁。同时让你对各个 loader 有个全局概览:
// 通过require导入path
const path = require('path');
module.exports = {
mode: 'development', //默认为线上模式, 这里指定为开发模式
entry: {
index: './js/index.js',
test: './js/test.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'bable-loader',
},
],
},
};
- test: 通过正则匹配需要loader处理的文件
- exclude: 通过正则匹配不需要loader处理的文件
- loader: 指定使用哪个loader来处理符合条件为文件
module.rules属性是一个数组中存放了多个对象,其中每一个对象代表一个loader的配置信息。
插件(plugins)
插件 是 webpack 的支柱功能。Webpack 自身也是构建于你在 webpack 配置中用到的 相同的插件系统 之上! 插件目的在于解决loader无法实现的其他事情。Webpack 提供很多开箱即用的 插件。
html-webpack-plugin的使用
在这里以常用的插件html-webpack-plugin为例来理解插件改如何使用,我们还可以使用更多插件
安装
npm install --save-dev html-webpack-plugin@4.3.0
配置
- 导入html-webpack-plugin模块
const HtmlWebpackPlugin = require('html-webpack-plugin');
- 创建HtmlWebpackPlugin对象
plugins: [
new HtmlWebpackPlugin({
template: './search.html',
filename: 'search.html',
chunks: ['search'],
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true,
},
}),
],
- template:需要处理的HTML文件的相对路径
- filename:处理完成后新的文件名称,存放路径为:在出口中配置的path属性
- chunks:指定该html文件需要引入的js文件,把单个或多个入口的键以字符串的形式放入数组
- removeComments: 删除html中的注释
- collapseWhitespace: 删除html中的空格
- removeAttributeQuotes: 删除html标签属性值的双引号
- 需要处理多个html文件就在
plugins中加入多个HtmlWebpackPlugin对象即可。
html-webpack-plugin插件的更多配置,这里的配置不是通用的,需要根据每个插件的文档进行配置
模式(mode)
webpack有development(开发模式)和production(生产模式)两种处理模式
module.exports = {
mode: 'production'
};
- 不配置该项默认为生产模式
- 初浅的理解
- 开发模式:实现主要功能的情况下,尽可能让人还能看的懂处理完后的代码,方便排查错误
- 生产模式:尽可能让代码性能更高,人基本已经很难看懂了
- 两种模式的本质是开发模式只使用了功能性的plugin,而生产模式还使用了提高代码性能的plugin。详情
总结
由于入口出口写法方式和组合很多、很乱,总结一下:
入口
- 入口有字符串的写法和对象的写法,字符串的写法只支持单入口,对象写法单入口多入口都可以
- 入口的写法推荐用方式二便于修改,更灵活
出口
- 推荐多出口的方式,使用占位符来确保每个文件具有唯一的名称
举例
按照推荐的写法也就是说只需要对入口进行配置就可以了,更多出口配置
const path = require('path');
module.exports = {
entry: {
index: './js/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
};
3.实际应用
js
通过babel-loader我们可以可以将es6代码编译为以ECMAScript 2015为标准的js代码 其实只对es6新增的语法进行了处理,对新增的函数和静态方法未进行处理
core-js
通过core-js对es6中的新的函数和静态方法进行处理的包
- 安装
npm install --save-dev core-js@3.6.5
- 使用
在入口文件导入
core-js/stable
import "core-js/stable";
综合应用
安装包
npm install --save-dev @babel/core@7.11.0
npm install --save-dev @babel/preset-env@7.11.0
npm install --save-dev babel-loader@8.1.0
npm install --save-dev core-js@3.6.5
配置
- 入口文件导入core-js
import "core-js/stable";
- webpack配置文件
const path = require('path');
module.exports = {
mode: 'development',
entry: {
index: './js/index.js',
test: './js/test.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
},
],
},
};
html
综合应用
- 安装
npm install --save-dev html-webpack-plugin@4.3.0
- 配置
- 导入模块
const HtmlWebpackPlugin = require('html-webpack-plugin');- 添加HtmlWebpackPlugin对象
plugins: [ new HtmlWebpackPlugin({ template: './search.html', filename: 'search.html', chunks: ['search'], minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true, }, }), ],
css
安装loader
- css-loader 协助webpack解析需要导入的css文件
npm install --save-dev css-loader@4.1.1
npm install --save-dev style-loader@1.2.1
npm install --save-dev mini-css-extract-plugin@0.9.0
- style-loader(不推荐) 将引用的css写入HTML的style标签中
- mini-css-extract-plugin(推荐) 将css作为文件引入
导入css
在入口文件中导入css
import './../css/base.css';
import './../css/cssreset-min.css';
import './../css/stylte.css';
配置文件
// 通过require导入path
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// const { loader } = require('mini-css-extract-plugin');
module.exports = {
mode: 'development', //默认为线上模式, 这里指定为开发模式
entry: {
index: './js/index.js',
test: './js/test.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].css',
}),
],
};
- css-loader 负责识别入口文件中导入的css文件
- mini-css-extract-plugin 负责压缩css文件并使用link标签引入html
- filename:通过改属性指定处理完的css文件存放位置,更多配置
图片
用file-loader来处理css中引入的图片(字体、字体图标)都是可以的
- file-loader
- url-loader
安装
npm install --save-dev file-loader@6.0.0
npm install --save-dev url-loader@4.1.0
- 只对图片进行打包,安装file-loader就行
- 需要对文件进行转码、设置MIME 类型并打包就两个都装只对url-loader进行配置就可以
个人理解url-loader是基于file-loader的基础上做了一些扩展,所以两个都需要安装并对url-loader进行配置就可以
配置
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'img/',
limit: 8192,
esModule: false, // 不启用js模块语法
},
},
],
},
- name:属性指定指定出后文件的名称,name、ext属于占位符。更多占位符
- outputPath:指定处理后的图片保存位置(相对于出口设置的位置)
- limit:指定文件是否进行base64转码,默认值true,当为数值时单位为B,为0时等价于false
- esModule:是否启用模块语法
- options:更多配置 同一个对象中存在如下冲突
- 使用options属性时不能使用use属性
- 使用options属性时loader属性的不能为数组
css中引入图片的处理
css引用图片路径不正确
由于图片由file-loader放在了指定路径下,需要调整css中引用图片的设置
css相关的处理由mini-css-extract-plugin处理,做如下调整:
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
},
},
'css-loader',
],
},
html中引入的图片
使用html-withimg-loader识别这部分图片,由url-loader对这部分图片进行打包或base64转码
安装
npm install --save-dev html-withimg-loader@0.1.16
配置
// 处理Html文件
{
test: /\.(html|htm)$/,
loader: 'html-withimg-loader',
},
此时处理完成后img标签的src属性被设置为了对象
需要修改url-loader配置esModule为false解决此问题
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'img/',
limit: 8192,
esModule: false,
},
},
],
},
字体图标文件
通过url-loader打包
配置
{
test: /\.(ttf|woff|woff2)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
name: '[name].[ext]',
outputPath: 'fonts/',
},
},
],
},
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: 'development', //默认为线上模式, 这里指定为开发模式
entry: {
index: './js/index.js',
test: './js/test.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
module: {
rules: [
// 处理js文件
{
test: /\.js$/,
exclude: /node_modules/,
loader: ['babel-loader'],
},
// 处理css文件
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
},
},
'css-loader',
],
},
// 处理Html文件
{
test: /\.(html|htm)$/,
loader: 'html-withimg-loader',
},
// 处理图片
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'img/',
limit: 8192, //指定是否进行base64转
esModule: false, // 不以es6模块的形式导出
},
},
],
},
// 处理字体、图标
{
test: /\.(ttf|woff|woff2)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
name: '[name].[ext]',
outputPath: 'fonts/',
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html',
chunks: ['index'],
}),
new HtmlWebpackPlugin({
template: './test.html',
filename: 'good.html',
chunks: ['test', 'index'],
}),
new MiniCssExtractPlugin({
filename: 'css/[name].css',
}),
],
};
4.搭建开发环境
通过webpack-dev-server的来实现类似于vscode中live-server插件的效果
安装
npm install --save-dev webpack-dev-server@3.11.0
配置
启动命令配置
"scripts": {
"webpack": "webpack --config webpack.config.js",
"dev": "webpack-dev-server --open chrome"
},