一.创建项目
废话不多说,直接开始初始化一个weboack的项目
yarn init -y
yarn add webpack webpack-cli --dev
项目目录:
二.测试
新建一些文件夹和文件按,随便写点东西
// src/index.js
console.log("webpack");
// index.html
<h1>Hello, world!</h1>
<script src="./src/index.js"></script>
用live server
打开 html:
三.利用 webpack 打包
npx 可以让我们直接运行node_modules下库的自带命令行,而不用写 node_modules下的相对路径
npx webpack
打包完成后,可以看到项目中多了一个 dist 目录:
四.写点内容
接下来,首先修改一下 index.html
文件, 方便后面使用打包后使用的js文件
<h1>Hello, world!</h1>
<script src="./dist/main.js"></script>
在 src/data.js
export function getBlogPosts() {
return ['博客1', '博客2', '博客3']
}
修改index.js 内容,添加打印 博客数据的代码
import { getBlogPosts } from './data';
console.log(getBlogPosts());
完事后,执行npx webpack
,可以看到,打包后的js文件内容
(()=>{"use strict";console.log(["博客1","博客2","博客3"])})();
很明显简化了console的内容,还对代码进行了压缩,说明webpack,智能的判断了代码的逻辑。
在回到浏览器,查看
控制台打印了三个博客列表的数据
五.webpack配置文件
webpack 最核心的就是它的配置文件啦~,文档都有写的很详细,可以修改入口文件
、配置出口
、通过 loader
加载不同的文件,在通过 plugins
,在打包过程提供一些代码优化或者是其他的操作,现在我们来测试一下,看看把打包后的文件名修改一下:
新建 webpack.config.js
const path = require('path');
module.exports = {
mode: "development", // 模式 开发/生产
entry: "./src/index.js", // 入口
output: { // 出口
filename: "dist.js", // 打包文件
path: path.resolve(__dirname, "dist"), // 打包文件路径
},
};
执行 npx webpack
,dist目录下就多了一个dist.js
文件,打开可以看到
接下来,修改
index.html
<script src="./dist/dist.js"></script>
那么之前的 main.js ,就不需要了,我们删除就好了。
六.使用loader来加载css文件,图片文件以及静态资源
修改index.js
,根据获取出来的博客列表的数据,来生成一组ul>li元素展示
import { getBlogPosts } from './data';
const blogs = getBlogPosts();
const ul = document.createElement('ul');
blogs.forEach((blog) => {
const li = document.createElement('li');
li.innerText = blog;
ul.appendChild(li);
})
document.body.appendChild(ul);
执行 npx webpack
,回到页面:
新建 src/style.css
,写一点简单css代码调整一下:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: sans-serif;
list-style: none;
}
body {
display: grid;
place-items: center;
}
li {
padding: 12px;
}
img {
max-width: 500px;
}
回到 src/index.js
,导入刚写的css文件
...
import "./style.css";
..
我们先不使用 loader,执行 npx webpack
来打包看看
这里直接报错了,意思是我们需要一个合适的 loader 来处理这个文件类型,当前,没有配置加载程序来处理此文件。
那么,加载 css 文件,那么我们需要安装两个 loader
yarn add --dev style-loader css-loader
安装完成后,我们需要在 webpack.config.js
去配置一下:
const path = require('path');
module.exports = {
...
//
module: {
rules: [{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
}]
}
};
执行 npx webpack
,看到控制台输出 successfully
,回到页面
可以看到,css样式就应用上了。
那么如何,加载图片呢,对于图片和一些静态资源,webpack 原生支持,就不需要额外安装对应的 loader 了,直接在 webpack.config.js
配置一下:
...
module: {
rules: [{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource",
}
]
}
};
回到 index.js
,把图片导入,写点js代码把图片添加到页面上:
...
import CoderImage from "./assets/images/coder.jpg";
...
const image = document.createElement('img');
image.src = CoderImage;
document.body.prepend(image);
执行 npx webpack
, 回到页面查看,图片就显示到页面上啦。
七.使用 html-webpack-plugin
安装 html-webpack-plugin
yarn add html-webpack-plugin --dev
安装好后,来到 webpack.config.js
,添加一下配置
...
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
...
plugins: [new HtmlWebpackPlugin()],
};
执行 npx webpack
,可以看到 dist
目录下生成了一个 index.html
文件:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Webpack App</title>
<meta name="viewport" content="width=device-width, initial-scale=1"><script defer src="dist.js"></script></head>
<body>
</body>
</html>
打开到浏览器上看一看,可以看到效果是一样的
可以看到这个 html 的标题是默认的
回到 webpack.config.js
,
plugins: [new HtmlWebpackPlugin({
title: "博客列表",
})],
执行npx webpack
,可以看到就修改掉了
八.使用 babel-loader
如果是低版本的浏览器,那么就不得不得做兼容,比如,es6的代码就得转成 es5 等等.
安装 babel-loader 相关依赖
yarn add --dev babel-loader @babel/core @babel/preset-env
回到 webpack.config.js
,
...
module.exports = {
mode: "development",
// 方便看打包后的代码
devtool: "inline-source-map",
...
module: {
rules: [
...
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
}
}
]
},
};
写好以上配置后,执行`npx webpack`打包命令,可以看到把我们之前写的 `ES6` 的语法转成了 `ES5`匿名函数的形式,说明`babel-loader`就生效了。
九.使用 terser-webpack-plugin
一个很常见的应用场景,我们在开发完项目后,需要打包项目,压缩代码,减少后的文件体积。
安装 terser-webpack-plugin
yarn add --dev terser-webpack-plugin
回到 webpack.config.js
,
...
const TerserWebpackPlugin = require('terser-webpack-plugin');
...
// 优化
optimization: {
minimize: true, // 是否要压缩
minimizer: [new TerserWebpackPlugin()], // 使用什么缩工具
},
执行npx webpack
打包命令, 查看 dist/dist.js
代码被压缩了,之前的空格也没有了,后面还有很长的一段加密字符。
十.使用 webpack-dev-server
现在,我们需要在开发的时候,每次要改动的js之后都要重新打包,这样会比较繁琐,webpack 提供了 webpack-dev-server
开发服务器,它可以在启动之后,如果我们修改的是js代码,它就重新打包并刷新页面,现在我们来看一看吧~
安装
yarn add --dev webpack-dev-server
...
...
devServer: {
static: "./dist",
},
...
然后来到 package.json
,来配置一个启动命令:
...
"scripts": {
"start": "webpack serve --open"
},
...
然后在 Terminal
里面输入
yarn start
这样 webpack 就会启动 webpack-dev-server
,自动打开页面展示和之前的效果。
现在,我们随便在index.js
新增点内容,再来看看效果
...
const h1 = document.createElement('h1');
h1.innerText = "博客列表";
document.body.prepend(h1);
可以看到h1
标签就添加进来了
现在我们打包后的文件,这个 dist.js 的文件名每次都是一样的,但是浏览器会根据文件名进行缓存,一般我们为了避免浏览器会缓存,我们会给文件名添加一串随机的字符,每次更新之后都改为新的字符,那么webpack也支持自动在打包后生成新的一串字符。
我们来看一看怎么来实现。
回到 webpack.config.js
,修改一下配置:
output: {
// filename: "dist.js",
filename: "[name].[contenthash].js",
}
然后终止服务器运行,在运行 npx webpack
打包,可以看到生成的文件后就带有生成随机的字符串的文件名
我们再来index.js
, 随便注释一段代码:
// const h1 = document.createElement('h1');
// h1.innerText = "博客列表";
// document.body.prepend(h1);
再来打包观察:
这里也生成了新的随机字符串的文件,我们删除这四个文件,把上面注释的代码解开,在回到 webpack.config.js
文件,修改回去。
十一.配置别名
接下来,我们来设置设置一下别名,有时候我们在开发的过程中,文件嵌套的可能会比较深,要引入其他目录下的 js 文件,需要使用很多../../../ ....
来访问这个文件的路径,webpack 可以让我们指定一个文件别名,来把这一串相对路径,替换掉,这样就可以少些一些字符串.
在webpack.config.js
,添加一下配置:
resolves: {
alaias: {
'xxx', path.resolve(__dirname, "src/xxx"),
}
}
十二.使用 bundle-analyzer
有时候,我们可能需要打包后分析打包后的结果,哪个文件占的体积比较大,需要下一步的优化。webpack 也有一个可视化的打包分析工具,叫做 webpacl-bundle-analyzer
安装
yarn add --dev webpack-bundle-analyzer
在webpack.config.js
,添加一下配置:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
...
// 插件
plugins: [
...
new BundleAnalyzerPlugin(),
],
执行 npx webpack
,打包命令,就会自动打开到浏览器可视化展示:
可以看到 index.js
是体积最大的,这样就很直观分析了。
十三.总结
webpack 是很多构建工具的基础,它的出现改变了传统前端项目的开发方式,形成了工程化。
webpack 是什么,为什么要用 Webpack,webpack 的 loader 和 plugins 的使用方法等。
webpack 的知识太多了,本文只列举了常用的 loader 和 plugins,道路且长~
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 用于创建 HTML 页面并自动引入 JS 和 CSS
const TerserWebpackPlugin = require('terser-webpack-plugin'); // 压缩打包后的文件
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; //分析打包后体积较大的可视化插件
module.exports = {
mode: "development", // 模式 development, production 或 none
devtool: "inline-source-map", // 方便看打包后的代码
entry: "./src/index.js", // 入口
output: { // 出口
filename: "dist.js", // 打包文件
// filename: "[name].[contenthash].js", // 生成带有随机字符的文件
path: path.resolve(__dirname, "dist"), // 打包文件路径
},
// 解析
resolve: {
alias: {
// utils: path.resolve(__dirname, "src/utils"),
}
},
// 优化
optimization: {
minimize: true, // 是否要压缩
minimizer: [new TerserWebpackPlugin()], // 使用什么缩工具
},
devServer: {
static: "./dist",
},
// 插件
plugins: [new HtmlWebpackPlugin({
title: "博客列表",
}),
new BundleAnalyzerPlugin(),
],
// 模块
module: {
rules: [{ // 匹配规则
test: /\.css$/i,
use: ["style-loader", "css-loader"], // 使用工具
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/resource", // webpack 自带静态资源打包类型
},
{
test: /\.js$/,
exclude: /node_modules/, // 排除 不进行打包
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
}
}
]
},
};
十四.参考
webpack中文文档:webpack.docschina.org/