webpack
什么是 Webpack
官方解释:
webpack is a static module bundler for modern JavaScript applications.
翻译一下:webpack 是一个静态的模块化打包工具,为现代的 JavaScript 应用程序;
我们来对上面的解释进行拆解:
- 打包 bundler:webpack 可以将帮助我们进行打包,所以它是一个打包工具;
- 静态的 static:这样表述的原因是我们最终可以将代码打包成最终的静态资源(部署到静态服务器);
- 模块化 module:webpack 默认支持各种模块化开发,ES Module、CommonJS、AMD 等;
- 现代的 modern:现代前端的开发越来越复杂,催生了 webpack 的出现和发展;
即:无论开发使用什么语言,最终通过 webpack 将代码打包成普通的静态资源(详见下文:Webpack 依赖图);
环境
Webpack 的运行是依赖 Node 环境的,所以我们电脑上必须有 Node 环境;
安装
webpack 的安装目前分为两个:webpack(代码使用)、webpack-cli(命令行使用);
这里推荐局部安装:假如电脑上有 3 个项目:vue2,vue3,react;三个项目都需要打包,可能依赖的 webpack 版本不一样;
所以:应该每个项目有着自己的 webpack,需要用什么版本,在本地的局部环境安装对应的 webpack 版本即可;
1 | npm install webpack webpack-cli –g # 全局安装(不推荐) |
基础打包
默认打包
- 创建个文件夹,使用
npm init -y
创建 package.json; npm i webpack webpack-cli -D
安装局部环境依赖;- 在根目录下新建
src
文件夹,文件夹下新建入口文件index.js
,写入任意 js 代码; - 在根目录下
cmd
:通过npx webpack
进行打包 ==> 打包成功:根目录下生成dist
文件夹,下面有main.js
;(可以将此打包之后的 js 引入 html 中,可以正常运行); - 但是如果根目录下没有
src
文件夹 (其他名字的文件夹也不行),或者src
文件夹下的 js 不叫index.js
进行打包 ==> 打包失败;(即:文件夹必须叫 src,入口文件必须叫 index.js); - 那如果就不想有 src 文件夹或 index.js 如何进行打包呢?这里用到了配置参数;
配置参数
修改文件夹名为 location,下面 js 改为 main.js;
- 指定入口;
1 | npx webpack --entry ./location/main.js #-entry为入口文件的意思, 后面跟 入口文件的路径; |
如何修改打包之后的文件夹名和下面的 js 名呢?
- 指定输出文件夹名、输出文件名;
1 | npx webpack --entry ./location/main.js --output-filename fsl.js --output-path fsllala |
但是这样写配置参数,太长了,不方便,如何解决呢?==> 单独创建配置文件;
配置文件
在根目录下新建
webpack.config.js
(固定名字),里面进行参数配置;
此时目录结构如下:
1 | |—— node_modules |
webpack.config.js
其实是个模块,webpack 的运行环境为nodejs
,nodejs
会将该模块导出的内容进行读取;所以需要使用 node 的 CommonJs;不能使用 ES6 模块,即:
1 | // webpack.config.js文件 |
- 进行相关参数配置
1 | const path = require("path"); |
- 如果不想叫
webpack.config.js
,而是叫vue.config.js
,运行npx webpack
==> 报错;
1 | npx webpack --config vue.config.js # 通过指定配置文件名,可以解决 |
npm run build
是怎么做到打包的呢
1 | // package.json |
进阶打包
Webpack 依赖图
webpack 到底是如何对我们的项目进行打包的呢?
- 事实上 webpack 在处理应用程序时,它会根据命令或者配置文件找到入口文件;
- 从入口开始,会生成一个 依赖关系图,这个依赖关系图会包含应用程序中所需的所有模块(比如.js 文件、css 文件、图片、字 体等);
- 然后遍历图结构,打包一个个模块 (webpack 默认只给 JS 文件打包,别的文件需要根据文件的不同使用不同的 loader 来解析);
loader
新建目录结构如下:
1 | |—— node_modules |
验证 loader 作用
验证上问提及:webpack 默认只给 JS 文件打包,别的文件需要根据文件的不同使用不同的 loader 来解析;
期望效果:
- index.html 文件中仅引入打包之后的入口文件,别的不做任何操作;
- 页面展示有 css 样式的内容;
编写验证代码
- css 文件夹下新建 div_style.css
1 | /* css/div_style.css */ |
- components 文件夹下新建 div_cpns.js
1 | // components/div_cpns.js |
- 入口文件引入 div_cpns.js
1 | // src/index.js |
- 使用
npm run build
进行打包
1 | # package.json |
打包出错,打包结果如下图所示:
上面的错误信息告诉我们需要一个 loader 来加载这个 css 文件,但是 loader 是什么呢?
- loader 可以用于对模块的源代码进行转换;
- 我们可以将 css 文件也看成是一个模块,我们是通过 import 来加载这个模块的;
- 在加载这个模块时,webpack 其实并不知道如何对其进行加载,我们必须制定对应的 loader 来完成这个功能;
- webpack 默认支持对 js 文件的处理;其他文件需要根据文件的不同使用不同的 loader 来解析;
css-loader 与 style-loader
- css-loader:可以解析 css 文件的 loader。但该 loader 并不会将解析之后的 css 插入到页面中,即如果只使用该 loader 会产生 css 解析完了,但是页面没有效果的现象;
- style-loader:会将解析之后的 css 插入到页面,即完成插入 style 的操作;
loader 下载:
1 | npm install css-loader style-loader -D #loader其实都是研发环境的,生产环境都是解析之后的静态文件; |
loader 配置
- webpack.config.js 文件中的 module.rules 中允许我们配置多个 loader;
- module.rules 的配置如下:
- rules 属性对应的值是一个数组,数组中存放的是一个个的 Rule,Rule 是一个对象,对象中可以设置多个属性:
- test 属性:用于对 resource(资源)进行匹配的,通常会设置成正则表达式;
- use 属性:对应的值是一个数组,数组里为各种 loader;注意:loader 的执行顺序是从后往前的;
- use 属性数组内可以为对象,对象属性为:
- loader:必须有一个 loader 属性,对应的值是一个字符串;
- options:可选的属性,值是一个字符串或者对象,值会被传入到 loader 中
- query:目前已经使用 options 来替代;
- use 属性数组内可以为字符串,是 loader 属性的简写方式;
- rules 属性对应的值是一个数组,数组中存放的是一个个的 Rule,Rule 是一个对象,对象中可以设置多个属性:
1 | module.exports={ |
使用 npm run build
进行打包 ==> 打包成功;
index.html 引入打包之后的文件,查看效果:
1 | <script src="./dist/main.js"></script> |
less-loader
less 同理,环境不支持该预处理器,需将现将 less、sass 等编写的 css 需要通过工具转换成普通的 css;
loader 下载
1 | npm install less-loader -D |
配置 webpack.config.js
1 | module.exports={ |
PostCSS
参考文献:PostCss,PostCSS 真的太好用了!
loader 下载
1 | npm install postcss-loader -D |
autoprefixer
- 有一些 css 属性存在浏览器兼容问题,需要开发手动添加浏览器前缀;
- 而 Autoprefixer 将使用基于当前浏览器支持的特性和属性数据去为你自动添加前缀 (-webkit-,-ms-,-moz-)。你可以尝试下 Autoprefixer 的 demo:Autoprefixer CSS online
使用 postcss 插件 Autoprefixer:
- 下载
1 | npm install autoprefixer -D |
- 设置单独的 postcss 配置文件:根目录下,新建
postcss.config.js
(注意:因为 postcss 需要有对应的插件才会起效果,所以我们需要配置它的 plugin);
1 | // postcss.config.js |
- 设置 loader
1 | // webpack.config.js |
- 相关 css 代码
1 | /* css/div_style.css */ |
npm run build
进行打包,index.html 引入打包之后的文件,检查 css- 效果如下
postcss-preset-env
- 集成了 postcss 常用的插件 (Autoprefixer,polyfill……);
- 所以用 postcss-preset-env,就不需要安装使用 Autoprefixer 了,因为内部已经集成了 Autoprefixer;
使用 postcss 插件 postcss-preset-env 同 Autoprefixer 步骤;
Webpack 打包图片
asset module type
我们当前使用的 webpack 版本是 webpack5:
- 在 webpack5 之前,加载这些资源我们需要使用一些 loader,比如 raw-loader 、url-loader、file-loader;(需要下载对应的 loader,然后使用)
- 在 webpack5 开始,我们可以直接使用资源模块类型(asset module type),来替代上面的这些 loader;(不需要下载 loader)
** 资源模块类型 (asset module type)**,通过添加 4 种新的模块类型,来替换所有这些 loader:
- asset/resource 发送一个单独的文件并导出 URL;(之前通过使用 file-loader 实现)
- asset/inline 导出一个资源的 data URI;(之前通过使用 url-loader 实现)
- asset/source 导出资源的源代码(基本不用);(之前通过使用 raw-loader 实现)
- asset 在导出一个 data URI 和发送一个单独的文件之间自动选择;(之前通过使用 url-loader,并且配置资源体积限制实现)
asset module type 的使用
- 新建文件夹 img,用于存放图片;
- 在 components 下,新建 img_cpns.js;
1 | // src/components/img_cpns.js |
- 在入口文件里面引入 img_cpns.js,构成 webpack 的依赖图结构;
1 | // src/index.js |
- webpack5 版本开始,不需要下载资源 loader,只需要配置 asset module type 即可;
将图片全部转换为一个单独的文件
- 配置 webpack
1 | // webpack.config.js |
- 通过
npm run build
进行打包;观察打包之后的 dist 文件夹;**(每次打包前需要删除之前的 dist 文件夹,防止之前的分包依旧保留,后续可以通过配置实现自动删除)**
发现将原来的 ikun.jpg,打包成了 1d40d06e317136088c5a.jpg;然后 main.js 对打包之后的图片地址做了处理;
- 浏览器运行,可看到图片正常显示,图片地址为在线地址:http://127.0.0.1:5500/dist/1d40d06e317136088c5a.jpg
如何做到自定义输出文件名呢?
自定义输出文件名:官网
- 配置 webpack
1 | module.exports = { |
通过 npm run build
进行打包;观察打包之后的 dist 文件夹;**(每次打包前需要删除之前的 dist 文件夹,防止之前的分包依旧保留,后续可以通过配置实现自动删除)**
发现将原来的 ikun.jpg,打包成了:ikun_1d40d06e317136088c5a.jpg;
如何将图片资源放到一个单独的文件夹内呢?
- 配置 webpack
1 | generator: { |
将图片全部转换为 base64 格式;
优点:相比较于 asset/resource,少发送 (图片加载) 网络请求;
缺点:造成 JS 文件偏大,下载 JS 文件、解析本身消耗时间非常长 ==> 造成代码阻塞;
配置 webpack
1 | module.exports={ |
- 通过
npm run build
进行打包;观察打包之后的 dist 文件夹;**(每次打包前需要删除之前的 dist 文件夹,防止之前的分包依旧保留,后续可以通过配置实现自动删除)**
发现 dist 文件夹里面只有一个 main.js;
- 浏览器运行,可看到图片正常显示,图片地址为 base64:data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD…P2atuIjKPvHtU5hxbHHVqzLS6xGJv4G6CtISEIPRulecZn//Z
可通过合理的配置,决定图片的转化;
合理的配置:
小一点的图片:进行 base64 编码;
大一点的图片:单独的图片打包,形成 url 地址,单独的请求这个 url 图片;
配置 webpack:官网
1 | module.exports = { |
Babel
- webpack 可以打包 JS 文件,但是 ES6 + 的语法不会转化为 ES5;
- Babel 是一个工具链,主要用于旧浏览器或者环境中将 ECMAScript 2015 + 代码转换为向后兼容版本的 JavaScript;
- 包括:ES6+,TypeScript、Vue、React 等通过 Babel 转换为向后兼容版本的 JavaScript;
- 在线 Babel 转换:官网
插件
Babel 的使用,需要安装相应的插件 (这里不过多介绍,一般来说安装预设 preset 即可);
1 | # 基本不安装此插件 |
Babel 的预设 preset
集成了 Babel 常用的插件;
- 安装
1 | npm install @babel/preset-env -D #安装预设preset |
- 使用
1 | //webpack.config.js |
1 | // 新建babel.config.js |
- 入口文件
1 | // // src/index.js |
- 打包
npm run build
,查看打包之后的 main.js;(箭头函数转化为了普通函数)
1 | "hello babel".split(" ").map((function(l){return console.log(l)})); |
Plugin
- Loader 是用于特定的模块类型进行转换;(文件解析、转换)
- Plugin 可以用于执行更加广泛的任务,比如打包优化、资源管理、环境变量注入等;(文件解析、转换之外的所有事情);
- 官网
CleanWebpackPlugin
每次修改了一些配置,重新打包时,都需要手动删除 dist 文件夹,CleanWebpackPlugin 可以自动化删除 (需要配置输出目录)。
Tip:5.20.0 + 的版本,可以直接配置 output==> 官网
- 安装
1 | npm install clean-webpack-plugin -D |
- 配置
1 | const path = require("path"); |
- 测试
在之前打包的 dist 文件夹中,随便新建个文件,比如 abc.js==> 打包之后被清除;