Webpack 入门教程
webpack 是一个模块打包工具,可以把互相依赖的 HTML、CSS、JavaScript,以及图片、字体等资源文件,经过一些列的处理,打包成静态的前端项目。
为什么要用 webpack
为什么要用 webpack 呢?我们在传统的网页开发项目中,需要通过在 html 中引入大量的 JavaScript、CSS 等文件,不仅会导致命名冲突,还会使页面体积变大,因为如果是第三方库,需要加载所有代码。
<script src="./jquery.js"></script>
<script src="./index.js"></script>
<script src="./home.js"></script>
// index.js
var a = 1;
// home.js
var a = 2;
而在 node.js 出现之后,JavaScript 项目支持通过 require 进行模块化开发了,并且支持 npm 方便的管理依赖:
npm install someLib
require("someLib");
借着 Node.js 和浏览器 JS 语法的一致性,前端项目开始在 node.js 下开发,完成之后,把代码构建成浏览器支持的形式。对于 react 或 vue 这种组件化开发方式,因为有很多分散的文件,那么就特别需要这样的构建操作。 Webpack 就是进行这一步构建操作的,把 Node.js 模块化的代码转换为浏览器可执行的代码。它提供了 import 和 export ES 6 模块化的语法支持,然后通过分析代码中的 import 导入的依赖,把需要的代码加载进来。 在 webpack 中,任何文件都可以通过 import 导入,只要有对应的 loader 就可以:
import "style.css";
import "image/avatar.png";
在打包过程中还可以通过插件干预打包过程,例如剔除不必要的代码,形成体积更小的项目。 好,我们具体的来看一个使用 webpack 打包项目的例子。
安装 webpack
Webpack 是一个基于 Node.js 的框架,在开发之前,先确保你的电脑里边已经安装了 Node.js。 接下来我们创建一个 Node.js 项目,在一个合适的目录下边,创建项目目录,这里我把它叫做 blog:
mkdir blog
cd blog
yarn init -y
这个项目我们要展示一个简单的博客列表,利用 Webpack,来对项目所涉及的依赖进行打包,创建完成之后进入到这个目录里边,初始化 node.js 项目,这里我使用 yarn 依赖管理工具,你也可以使用 npm。 要初始化项目,运行下方命令:
yarn init --y
--y 参数,意思就是生成的 package.json 文件里所有的配置项都取默认值。 创建完成之后我们添加 webpack 依赖:
yarn add webpack webpack-cli --dev
--dev 是把 webpack 相关的依赖,安装到开发者依赖里边,因为 webpack 只有在开发的时候才会用到,他最后打包生成的代码里边,不需要再使用 webpack 了。 安装完成之后,使用 vscode 打开咱们的项目:
code-insiders .
这里我使用的是内侧版的 vs code,所以这里的命令是 code insiders,如果你使用的是正式版的,就是 code
命令。
打开之后我们先新建一个 src 目录,这里边就会存放我们要写的源代码,在 src 下再新建一个 index.js 文件,这里边我们先编写一些简单的测试代码,例如使用一个 console.log,打印出 hello world 字样:
console.log("hello world");
在项目的根目录下,再创建一个 index.html 文件,在它里边我们会加载 index js ,这里
- 使用快捷命令
html:5
,按 TAB 补全 - 在 body 里边我们使用 script 来加载 index.js,src 属性设置为当前目录下边的 src 目录下的 index.js。
- 在里边我们编写测试文本,例如使用一个 h1 展示 hello world,这样方便我们测试
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Webpack 教程</title>
</head>
<body>
<h1>Hello World</h1>
<script src="./src/index.js"></script>
</body>
</html>
好,现在我们使用 live server 来运行一下。
live server 是 vs code 的一个插件,它是用来实时预览 HTML 文件的,这个可以通过插件市场来安装。
我们在 index.html 文件上面右击,选择 open with live server,它会自动帮我们打开浏览器。我们看一下开发者工具,打开 console 这个面板,可以看到 Hello World 这个字符打印出来了。 接下来我们试试使用 webpack 打包一下代码,虽然现在我们还没有用到任何的 import 语句,但是我们先熟悉一下 webpack 的执行流程。打开 vs code 的命令行,运行:
npx webpack
这样就执行了打包命令,npx 可以让我们直接运行 node_modules 下边安装的库中自带的命令,就不用写 node_modules 这一串相对路径了。打包完成之后,我们可以看到项目里边多了一个 dist 目录,下边有一个 main.js,我们打开它,可以看到它的代码跟咱们的 src/index.js 里边的是一样的,因为我们没有用到任何 import 来导入其他的依赖。 接下来我们把 index.html 里边的 index.js 这个引用改成使用 dist 下边的 main.js,因为后面我们要使用的都是打包后的 js 文件。
<script src="./dist/main.js"></script>
我们试试在有依赖的情况下,打包后的代码是什么样的,在 src 下再新建一个 data.js 文件,里边导出一个函数,返回一串示例的博客列表数据:
export function getBlogPosts() {
return ["博客 1", "博客 2", "博客 3"];
}
之后在 index.js 里边把 console.log,改成调用 getBlogPost() 函数,这里 vs code 会自动帮我们把 getBlogPost,从 data.js 文件里边导入进来。
import { getBlogPosts } from "./data.js";
console.log(getBlogPosts());
好,我们再运行一下npx webpack
看一下结果,打开 main.js,可以看到这个代码就简化了,直接 console.log 这个博客列表数据了,说明 webpack 智能的判断了代码逻辑,通过 import 把代码拿过来,然后分析代码的执行逻辑,最后得出我们只打印了博客列表数据,就生成了简化的代码。
Webpack 配置文件
Webpack 最核心的一个部分是它的配置文件,在里边我们可以修改入口的 JS 文件,也就是说从哪个文件里边开始寻找 import 依赖,还可以配置出口,也就是最后生成的 JS 文件的一些信息,还能够通过 loader 加载不同类型的文件,再可以通过 plugins 在打包的过程中,对代码进行一些优化或者其他的操作。 我们来测试一下看看,把打包后的文件名修改一下,我们在这里先新建一个 webpack.config.js 文件,这里边使用的是 Node.js 的模块化语法,使用 module.exports,导出一个空的对象,在里边我们配置 webpack 的配置项:
- 我们添加一个 mode 属性,因为我们之前打包的时候,命令行提示了这个 mode 选项没有设置, webpack 默认取的是 production,但是我们也可以设置为 development 开发环境,这样的话在开发环境下, webpack 打包的代码会不太一样,方便我们开发者进行调试,这里我们把 mode 先设置成 development。
- 看一下 entry,这里我们还是取的默认值,可以把它拿出来,看一下是怎么设置的,这里可以直接把咱们的入口文件路径给它写上,./src/index js。
- 配置打包后的文件名,我们使用 output 配置项,传递一个对象属性,配置 filename,这个就是打包后的文件名,例如我们改成 dist.js,然后存放目录也可以改一下,现在是 dist,如果要改成别的话,可以给它配置一个 path 属性,这里我们可以利用 Node.js 提供的 path 库,来获取 webpack.config.js 所在的目录,基于它我们再去找到一个新的目录,来存放我们打包后的文件,例如说我们还是把它放到 dist 里边。我们可以调用 path.resolve(),resolve 接收多个参数可以指定多级目录,例如第一级我们设置为 __dirname,然后第二级设置为 dist,这样它就会放到 dist 目录下边了,你也可以把它改成别的名字。
const path = require("path");
module.exports = {
entry: "./src/index.js",
output: {
filename: "dist.js",
path: path.resolve(__dirname, "dist"),
},
};
好,我们运行一下 npx webpack,打包一下看一下结果,可以看到 dist 的目录下边,多了一个 dist.js 文件,这里面的代码多了许多,因为现在我们改成了开发模式。 接下来我们把 index.html 中的 js 文件引入,改成使用 dist.js,之前的 main.js 这里我们就不需要了,删除。
<script ... dist.js />
使用 Webpack Loader
接下来我们使用 webpack loader,来加载 CSS 文件,我们先把 html 中的 h1 删除,这里不需要它了:
<body></body>
index.js 里边的代码,我们把它改一下:
- 根据获取出来的博客列表数据,生成一组 ul 和 li 元素展示。
- 我们把 getBlogPost 函数返回的结果保存到一个 blogs 常量里边。
- 创建 ul 元素并遍历 blogs 这个数组。
import { getBlogPosts } from "./data.js";
const blogs = getBlogPosts();
const ul = document.createElement("ul");
blogs.forEach((blog) => {
const li = document.createElement("li");
li.innerText = blog;
ul.append(li);
});
document.body.append(ul);
这里代码的意思就是说,我们遍历 blogs,对于每一个博客列表数据,创建一个 li 元素,然后给 li 元素内部的文本设置为 blog 元素代表的文本值,然后把它添加到 ul 元素中,最后使用 document.body.appendChild(ul)
,把这个 ul 放到 body 元素里边,这样我们就在 js 里边创建好了 HTML 元素。
好,我们测试一下,运行npx webpack
先打包,然后回到浏览器里边看一下,可以看到这 3 个博客列表数据就都显示出来了。
下面我们就要加载 css,先创建 css 文件,在 src 下新建一个 style.css 文件,它里边的代码不是重点,就是一些简单的样式调整:
* {
padding: 0;
margin: 0;
font-family: sans-serif;
}
body {
display: grid;
place-items: center;
height: 100vh;
}
ul {
list-style: none;
}
li {
padding: 12px;
}
img {
max-width: 500px;
}
之后我们 在 index. js 里边把它导入进来,这样它就能够充分利用 webpack 的特性了,如果在 index.html 中导入,那就和普通导入 CSS 的方式没有区别,不能对 CSS 样式进行优化或者其他的操作了。这里在 index.js 里边我们使用 impor 导入 css:
import "./style.css"
我们先试试不使用 loader 的话,打包会出现什么样的效果,运行 npx webpack
,可以看到提示出错了,这里它就告诉我们了,我们可能需要一个合适的 loader,来加载这样的文件类型。
要加载 CSS 文件,我们需要安装两个 loader,一个叫 style loader,另一个是 CSS loader。
yarn add style-loader css-loader --dev
安装完成之后,我们需要在 webpack 的配置文件里边去配置它,对于 loader,在 webpack 里边,我们需要先去匹配,以什么样的扩展名结尾的文件,去应用什么样的 loader。 在这里我们:
- 添加一个 module 配置项。
- 在里边配置 rules 配置项,它的值是一个数组,数组里边的每一个元素,都对应一个 loader 的配置,每个 loader 的配置都包含匹配扩展名,以及使用哪些 loader 和它相关的选项,例如说我们这里配置 CSS loader,先给 rules 传递一个对象。
- 在对象中配置 test 属性,它的值是一个正则表达式,用于匹配文件名,这里我们匹配所有以 .css 结尾的文件,那么这里我们先传递一个正在表达式,然后使用
\.
来匹配文件名里边的点号,因为点号在正则表达式中有特殊的含义,所以需要反/进行转义,然后写上 CSS 这个扩展名,再接着使用一个$
符号,来匹配文件名的结尾,后边我们可以加上一个i
来忽略大小写。 - 给它传递一个 use 属性,就是说使用哪些 loader,这里我们使用刚才安装好的 style loader 和 css loader。
// webpack.config.js
module: {
rules: [
{
test: /\.css$/i, // 匹配文件结尾,正则 - 忽略大小写
use: ['style-loader', 'css-loader'], // 使用哪些 Loader
},
],
},
好,现在我们打包再看一下,运行 npx webpack
,可以看到这个打包成功了,我们在浏览器上看一下,可以看到相应的样式也都应用上了,其他的像是 SASS 等 CSS 预处理文件,也可以通过相应的 loader 来这样配置。
加载图片
接下来我们看一下如何加载图片,对于图片等静态资源的文件,webpack 原生的支持,所以就不再需要额外的安装 loader 了,我们这里可以:
- 直接在 rules 里边,再添加一个配置对象。
- 设置 test 属性,这里匹配所有的图片文件,那么我们使用
\.
,然后使用一个小括号,里边我们要匹配多种图片的扩展名,例如 png,然后使用|
表示或, svg 或 jpg 或 jpeg 或 gif,然后加上$
,匹配扩展名这个结尾,再加上一个i
表示忽略大小写。 - 这里因为它是使用内置的 loader,所以使用 type 属性,设置 asset/resource 这样的值就可以了。
rules: [
// ...
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource', // 资源类型
}
],
接下来我们测试一下,先添加一张测试图片,在 src 下新建一个 assets 目录,再在它里边新建一个 images 目录,把图片 copy 过来,然后在 index.js 中创建一个 image 元素,把图片展示出来,这里我们先使用 import 把图片导入进来,给他一个名字,比如叫做 HeroImage,然后 from ./assets/images/hero.jpeg,这样导入之后,HeroImage 表示的就是打包后的图片的真实的路径,可以直接用于 img 元素的 src 属性上面。 接下来我们创建 image 元素,然后设置它的 src 属性值,为我们导入进来的 HeroImage,最后把它添加到 body 里边,这里我要把它放到 body 的开头。
import HeroImage from "./assets/images/hero.jpeg"; // 打包时替换成真实的路径
const image = document.createElement("img");
image.src = HeroImage;
document.body.prepend(image);
我们打包一下 npx webpack
。回到浏览器看一下,这个图片就正常的加载出来了,我们还可以看到在打包之后,这个图片的名字,也变成了随机的字符串。
使用插件
接下来我们看一下如何在 webpack 中使用插件。现在我们的 index.html 是手写的,非常容易出错,需要同步 src 下边的 JS 文件路径,而 webpack 有一个插件,可以自动生成 html 文件,这样就不需要我们再手动去编写代码了,这个插件叫做 HtmlWebpackPlugin。 我们先安装它,并添加到开发者依赖中:
yarn add html-webpack-plugin --dev
好打开 webpack.config.js,里边我们使用这个插件: 首先先导入进来,之后在配置对象里边,添加一个 plugins 配置项,它的值是一个数组,在里边我们可以加载多种插件,加上 HtmlWebpackPlugin,它导出的是一个构造函数,我们使用 new 调用它,这样就加载好了这个插件:
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {},
plugins: [new HtmlWebpackPlugin()],
};
好我们运行一下 npx webpack
,dsit 目录下会多一个 index.html,这个就是它自动帮我们生成的 html 代码,我们可以直接使用 live server 运行一下,可以看到展示的效果是一样的,那么之前的 HTML 文档可以删除了。
不过看一下这个 html 的标题是默认生成的,HtmlWebpackPlugin 插件支持我们传递参数,来自定义 html 代码的生成。例如,这里可以传递一个 title 属性,设置一下网页的标题,例如叫做博客列表:
new HtmlWebpackPlugin({title: "博客列表"}),
之后再重新打包一下,回到浏览器,可以看到这里网页的标题就变成了博客列表。
转译 ES6 为 ES5 插件
我们在开发前端项目的时候,有的时候会使用新的 ECMAScript 特性,但是要兼容低版本的浏览器,那么我们可以利用 Babel 这个工具,来转译咱们的 JS 代码。webpack 也支持相应的 loader,我们看一下来怎么实现。 首先安装 babel-loader,@babel/core,@babel/preset-env 这 3 个依赖:
yarn add --dev babel-loader @babel/core @babel/preset-env
安装完成之后:
- 在 webpack 配置项里边,我们再新添加一个 loader 配置,这里我们要匹配 JS 结尾的文件,那么使用 test,匹配 ./js 这个扩展名。
- 使用 exclude,把 nodule_modules 这个目录给去掉,这样它就不会转译它下边的代码。
- 使用 use 来配置使用哪些 loader,这里我们使用对象形式,因为我们需要给 loader,传递一些自定义的配置。
- 使用 loader 配置项,指定要使用哪个 loader,我们这里使用 babel loader。
- 使用 options 来给这个 loader 传递一些配置,配置 presets,使用 @babel/preset-env,这样就能够自动转译代码了。
- 为了方便我们看打包后的代码,我们可以在 webpack 的配置项里,添加一个 devtool 配置项,把它设置为 inline-source map,这样方便我们查看打包后的源代码。
devtool: 'inline-source-map', // 方便查看源码
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
}
}
}
]
}
好我们运行 npx webpack
打包看一下,先注意一下,这里我们 index.js 里使用了箭头函数,来作为 forEach 的回调函数,但是在 ES6 之前是不支持箭头函数的:
blogs.forEach((blog) => {
const li = document.createElement("li");
li.innerText = blog;
ul.appendChild(li);
});
那么这样,在打包后,应该它会转换成一个普通的函数,我们看一下是不是这样,现在已经打包完毕了,打开 dist.js ,我们搜索一下/src/index.js,看一下它里边的代码,这里可以看到,箭头函数转换成了普通的匿名函数,这种形式,说明咱们的 babel loader 就生效了。
压缩 JS 代码
再接下来,看一下 webpack 的另一个常见的场景,就是压缩打包后的 JS 代码,这样的话可以减少打包后的文件体积,他需要一个叫做 terser-webpack-plugin 的插件,我们这里先安装一下:
yarn add --dev terser-webpack-plugin
好安装完成之后,我们在 webpack.config.js 里边配置它。
- 导入进来,把它保存到一个叫做 terser-webpack-plugin 的常量里边。
- 在导出的配置对象里边,添加一个 optimization 配置项,配置 minimize 是否要压缩,把它的值设置为 true。
- 配置 minimizer,用什么工具来压缩,我们这里使用安装的 terser-webpack-plugin,这里直接调用 new TerserPlugin() 这个构造函数就可以了。
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
},
};
好我们测试一下,运行 npx webpack,再打开 dist.js,可以看到他把所有的空白都去掉了,并且这些变量什么的,都使用了简化的形式,后边还有一串加密的字符。
Dev Server 开发服务器
现在我们在开发的时候,需要每次在改动 JS 之后都要重新打包,webpack 提供了一个 dev server 开发服务器,它可以在启动之后,如果我们修改的 JS 代码,它就会自动重新打包并刷新页面,我们来看一看怎么来使用这个工具。首先先安装它 :
yarn add --dev webpack-dev-server
接下来我们需要指定 dev server 要从哪里去加载代码,我们打开 webpack.config.js,在配置项里边再添加一个 devServer 配置项,给他的值设置为一个对象,然后设置 static,给他指定咱们的 dist 目录:
devServer: {
static: './dist', // 从哪里找打包好的文件
},
接下来,为了方便我们运行开发服务器,我们在 package.json 里边再新添加一个 script,例如,我们可以使用 yarn start 来启动开发服务器,那么这里我们添加一个 scripts 配置项,然后在里边配置 start 命令,值为 webpack serve --open,这样就能够启动 webpack dev server,并自动打开浏览器:
"scripts": {
"start": "webpack serve --open", // 自动打开浏览器
},
好,我们运行一下试试,在命令行里运行 yarn start,可以看到他自动的帮我们把浏览器打开了,并且展示的效果和以前是一样的。好,我们再改一下 index.js 里边的代码,看一下它,会不会自动的帮我们重新打包,例如我们在添加完图片之后,再添加一个 h1,展示一些测试的文字,设置他的 innerText,比如说这里叫做博客列表,然后把它添加到 document.body 里边:
// ...
document.body.prepend(image);
const h1 = document.createElement("h1");
h1.innerText = "博客列表";
document.body.prepend(h1);
好我们回到浏览器里边再看一下,可以看到这个 h1 元素就添加进来了。
文件名缓存
现在我们打包后的文件,这个 dist.js 每次都是一样的,但是浏览器会根据这个文件名,进行缓存,一般我们为了避免浏览器进行缓存,我们会给文件名加上一串随机的字符,每次更新之后都改为新的字符,那么 webpack 也支持自动在打包后,生成新的一串字符,我们看一下怎么来实现。 打开 webpack.config.js,这里我们需要
- 配置 output,这里 filename 我们配置了 dist.js,但是我们也可以把它改成一个带有 hash,也就是不重复的字符串的文件名。
- 把它的值改成 [name][contenthash].js,这里 name 也可以写死,不过写 [name] 的话,webpack 会自动把它替换成 main,就是默认的文件名,contenthash 会每次根据文件的内容进行 hash 计算,得出一串不重复的字符:
output: {
filename: 'dist.js',
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
},
好我们来测试一下,先停止开发服务,然后运行 npx webpack
,可以看到它生成了这样的带有随机字符串的文件名,我们再改一下 index.js 里边的代码,比如说把这个 h1 这一段给去掉,再运行 npx webpack
,在之前我们看一下他这个是 5a94 开头,ff8e 结尾的,再运行一下看它生成什么样的,这里可以看到他生成了新的这个文件,这一串随机的字符串也修改了,好我们把这些先删除,然后把 index.js 的代码还原,这里我们先继续使用之前的 dist 文件名。
路径别名
接下来我们看一下,如何给导入的路径设置别名,有的时候,JS 文件所在的目录可能会嵌套的比较深,要引入其他的目录下边的 JS 文件,需要使用很多 ../
来访问这个相对路径。但是 webpack 可以让我们指定一个路径别名,来把这一串相对路径给替换掉,这样就少写一些字符串。
这个例子我们就随便测试一下,也不是特别有实际意义的,我们再一下新建一个 utils 目录,在里边再新建一个 date.js,在里边我们导出一个函数,把 date 对象转换成 年份-月份-日子这样的字符串,dateToStr 函数接收 date 参数,返回转换之后的字符串:
export function dateToStr(date) {
return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
}
之后,我们添加一个嵌套层次比较深的目录,在 src 下新建一个 test 目录,然后在里边再新建一个 date 目录,再在 date 下边我们新建一个 printDate.js 文件,这里边他会调用之前我们创建的 date.js 里边的 dateToStr 来打印日期,这里我们使用 console.log,然后调用 dateToStr,传递当前日期:
import { dateToStr } from "../../utils/date.js";
console.log(dateToStr(new Date()));
这里可以看到我们导入的时候,使用了两级相对路径,接下来我们需要在 index.js 里边,再把它导入进来,这样的话 webpack 才会发现这个文件,在 index.js 中我们导入./test/printDate.js 这个文件:
import "./test/date/printDate";
好,我们配置路径别名,打开 webpack.config.js,再添加一个 resolve 配置项,它的值也是一个对象,然后添加 alias 配置项,它里面的属性名就是路径别名,值就是真实的路径:
resolve: {
alias: {
utils: path.resolve(__dirname, 'src/utils/'),
},
},
下面我们就可以在 print.js 里边,把这两个../
去掉了,直接使用 utils
这个别名,最后他就会转换成真实的地址:
import {dateToStr} from "utils/date.js;
我们运行一下npx webpack
,这里只要打包没有错误,就说明咱们这个路径别名就生效了。
代码分析 Analyzer
有时候我们可能需要分析一下,打包后的结果,哪个文件占的体积比较大,再进行下一步的优化,那么 webpack 也有一个可视化的打包分析工具,叫做 webpack bundle analyzer,我们先安装一下看看它怎么使用:
yarn add --dev webpack-bundle-analyzer
安装完成之后,在 webpack.config.js 里边把它导入进来,它添加到 plugins 数组里边就可以了,这里调用 new BundleAnalyzerPlugin():
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
这里注意的是,webpack-bundle-analyzer,这个导入进来的是一个对象,我们在需要访问他里边同名的 BundleAnalyzerPlugin 构造函数才可以初始化。
这个工具会在我们运行 npx webpack
的时候自动打开,我们现在就运行一下,可以看到它自动打开了,这个可视化的工具,可以看到是咱们的 index.js 文件所占的体积最大,虽然他的体积并不是特别的大,但是在其他的所有的文件里边,他占用的算是比较大的,其他的都是比较小的。
小结
好了这个视频我们介绍了 webpack,为什么使用它,以及使用了这样一个实例演示了它常用的配置项的用法,随着项目规模的增加,你可能会遇到更多的 webpack 配置项,loader 和 plugins,这些 webpack 官网都有详细的介绍,那么这里就需要你再深入的去研究了,好了这节课你学会了吗,如果有帮助请三连并关注,想学更多的开发知识,可以在评论区留言,感谢观看!
一系列的课程让你成为高级前端工程师。课程覆盖工作中所有常用的知识点和背后的使用逻辑,示例全部都为工作项目简化而来,学完即可直接上手开发!
即使你已经是高级前端工程师,在课程里也可能会发现新的知识点和技巧,让你的工作更加轻松!
《React 完全指南》课程,包含 React、React Router 和 Redux 详细介绍,所有示例改编自真实工作代码。点击查看详情。
《Vue 3.x 全家桶完全指南与实战》课程,包括 Vue 3.x、TypeScript、Vue Router 4.x、Vuex 4.x 所有初级到高级的语法特性详解,让你完全胜任 Vue 前端开发的工作。点击查看详情。
《React即时通信UI实战》课程,利用 Storybook、Styled-components、React-Spring 打造属于自己的组件库。
《JavaScript 基础语法详解》本人所著图书,包含 JavaScript 全面的语法知识和新特性, 可在京东、当当、淘宝等各大电商购买