认识webpack
事实上随着前端的快速发展,目前前端的开发已经变的越来越复杂了:
- 比如开发过程中我们需要通过模块化的方式来开发;
- 比如也会使用一些高级的特性来加快我们的开发效率或者安全性,比如通过ES6+、TypeScript开发脚本逻辑,通过sass、less等方式来编写css样式代码;
- 比如开发过程中,我们还希望实时的监听文件的变化来并且反映到浏览器上,提高开发的效率;
- 比如开发完成后我们还需要将代码进行压缩、合并以及其他相关的优化;
- 等等….
但是对于很多的前端开发者来说,并不需要思考这些问题,日常的开发中根本就没有面临这些问题,这是因为目前前端开发我们通常都会直接使用三大框架来开发:Vue、React、Angular,使用这三大框架开发我们都是借助于脚手架(CLI)的。但是本质上,Vue-CLI、create-react-app、Angular-CLI都是基于webpack来帮助我们支持模块化、less、TypeScript、打包优化等的,所以学习webpack也是很重要的。
事实上我们上面提到的所有脚手架都是依赖于webpack的:
Webpack到底是什么呢?
我们先来看一下官方的解释:
webpack is a static module bundler for modern JavaScript applications.
webpack是一个为现代的JavaScript应用程序准备的静态的模块化打包工具。
我们来对上面的解释进行拆解:
- 现代的modern:我们前端说过,正是因为现代前端开发面临各种各样的问题,才催生了webpack的出现和发展;
- 静态的static:这样表述的原因是我们最终可以将代码打包成最终的静态资源(部署到静态服务器);
- 模块化module:webpack默认支持各种模块化开发,ES Module、CommonJS、AMD等;
- 打包bundler:webpack可以将帮助我们进行打包,所以它是一个打包工具;
Webpack官方的图片:
Vue项目加载的文件有哪些呢?
- JavaScript的打包:
将ES6转换成ES5的语法;
TypeScript的处理,将其转换成JavaScript; - Css的处理:
CSS文件模块的加载、提取;
Less、Sass等预处理器的处理; - 资源文件img、font:
图片img文件的加载;
字体font文件的加载; - HTML资源的处理:
打包HTML资源文件; - 处理vue项目的SFC文件.vue文件;
Webpack的使用前提
webpack的官方文档是https://webpack.js.org/
webpack的中文官方文档是https://webpack.docschina.org/
DOCUMENTATION:文档详情,也是我们最关注的
Webpack的运行是依赖Node环境的,所以我们电脑上必须有Node环境,所以我们需要先安装Node.js,并且同时会安装npm。我当前电脑上的node版本是v14.15.5,npm版本是6.14.11(你也可以使用nvm或者n来管理Node版本)。
Node官方网站:https://nodejs.org/
查看node和npm版本:
Webpack的安装
webpack的安装目前分为两个:webpack、webpack-cli。
那么它们是什么关系呢?
执行webpack命令,会执行node_modules下的.bin目录下的webpack,webpack在执行时是依赖webpack-cli的,如果没有安装就会报错。而webpack-cli中代码执行时,才是真正调用webpack进行编译和打包的过程,所以在安装webpack时,我们需要同时安装webpack-cli(一句话就是:webpack调用webpack-cli,webpack-cli再调用webpack)。
当我们使用命令行打包webpack项目就需要webpack-cli了,第三方的脚手架事实上是没有使用webpack-cli的,而是类似于自己的vue-service-cli的东西。
全局安装:在任何地方都可以使用webpack(不推荐)
npm install webpack webpack-cli –g # 全局安装
局部安装:只有当前项目可以使用(推荐)
npm install webpack webpack-cli –D # 局部安装
Webpack的默认打包
我们新建一个简单的项目,写一些简单的js代码,但是这些js代码默认不能直接在浏览器运行的,总会有这样那样的问题,我们可以通过webpack进行打包,之后运行打包之后的代码。
在项目目录下打开终端,直接执行 webpack
命令,会生成一个dist文件夹
,里面存放一个main.js
的文件,就是我们打包之后的文件,这个文件中的代码被压缩了,并且打包之后的文件是可以直接被浏览器运行的。
另外我们发现代码中依然存在ES6的语法,比如箭头函数、const等,这是因为默认情况下webpack并不清楚我们打包后的文件是否需要转成ES5之前的语法,后续我们需要通过babel来进行转换和设置。
创建局部的webpack
前面我们直接执行webpack命令使用的是全局的webpack,但是每个项目依赖的webpack版本可能不一样,这就可能导致打包失败,实际项目中我们一般都使用局部的webpack。如果希望使用局部的可以按照下面的步骤来操作:
- cd到项目中,执行
npm init -y
这个命令会生成package.json文件,用于管理项目的信息、库依赖等。
npm init -y
// -y代表所有选项都取默认值,不用一步一步问你了
- 安装局部的webpack
npm install webpack webpack-cli -D
// -D代表开发依赖,开发阶段才会用到
// -S代表生产依赖,开发、生产都会用到
执行完毕会生成两个文件:一个是package-lock.json文件,它会记录真正安装的版本号,并且在下次安装的时候直接去缓存中找就行了。另外一个就是node_modules
,这个文件夹下就是刚才我们安装webpack的各种依赖包。
安装完你肯定想,直接在项目终端中执行webpack命令不就可以使用局部的了吗?其实不是,直接在项目中执行webpack命令使用的还是全局的。使用局部的webpack我们需要找到.bin下面的webpack,然后执行才可以:
使用本地webpack麻烦的方式:
- 使用局部的webpack
上面方式比较麻烦,其实我们使用npx webpack
,也可以启动局部的webpack打包。
npx webpack
webpack打包,默认情况下,入口文件为src/index.js
,出口文件为dist
,那万一没有存在index.js或者dist文件夹呢?我们可以给命令加一些额外的参数:
npx webpack --entry ./src/main.js --output-path ./buid
这样,它就会将main.js作为入口文件,打包后的文件保存在build文件夹中。
- 在package.json中创建scripts脚本
上面npx的方式,我们开发中也基本不用,我们一般在package.json中创建scripts脚本,执行脚本打包即可。
npm run build
使用npm run build
才是我们开发中最常用的方式。
Webpack打包的入口和出口
上面用命令行指定入口出口的方式,项目中我们基本不用。我们一般创建一个webpack.config.js
,然后按照如下方式添加入口出口,继续执行npm run build,依然可以正常打包。
指定配置文件名称
但是如果我们的配置文件并不是webpack.config.js的名字,而是其他的名字呢?
比如我们将webpack.config.js修改成了 wk.config.js,这个时候我们可以通过 --config
来指定对应的配置文件,所以我们可以在package.json中增加一个新的脚本,如下:
但是我们不推荐这么做,就直接叫webpack.config.js
就行了。
编写案例代码
我们创建一个component.js,通过JavaScript创建了一个元素,并且希望给它设置一些样式:
执行npm run build会报错:
Webpack的依赖图
webpack到底是如何对我们的项目进行打包的呢?
事实上webpack在处理应用程序时,它会根据命令或者配置文件找到入口文件。从入口开始,会生成一个依赖关系图(当然如果没有在这个依赖关系图中的文件是不会被打包的),这个依赖关系图会包含应用程序中所需的所有模块(比如.js文件、css文件、图片、字体等)。然后遍历图结构,打包一个个模块,然后根据文件的不同使用不同的loader来解析。上面打包报错就是因为我们没有合适的loader。
css-loader的使用
上面的错误信息告诉我们需要一个loader来加载这个css文件,但是loader是什么呢?
loader 可以用于对模块的源代码进行转换,我们可以将css文件也看成是一个模块,我们是通过import来加载这个模块的,在加载这个模块时,webpack其实并不知道如何对其进行加载,我们必须制定对应的loader来完成这个功能。
那么我们需要一个什么样的loader呢?
对于加载css文件来说,我们需要一个可以读取css文件的loader,这个loader最常用的是css-loader,安装如下:
npm install css-loader -D
css-loader的使用方案
如何使用这个loader来加载css文件呢?有三种方式:
- 内联方式;
在引入的样式前加上使用的loader,并且使用!分割。
内联方式使用较少,因为不方便管理。
-
CLI方式(webpack5中不再使用);
在webpack5的文档中已经没有了--module-bind。
实际应用中也比较少使用,因为不方便管理。 -
loader配置方式;
loader配置方式
配置方式表示的意思是在我们的webpack.config.js文件中写明配置信息。module.rules中允许我们配置多个loader(因为我们也会继续使用其他的loader,来完成其他文件的加载),这种方式可以更好的表示loader的配置,也方便后期的维护,同时也让你对各个loader有一个全局的概览。
module.rules的配置如下:
rules属性对应的值是一个数组:[Rule],数组中存放的是一个个的Rule,Rule是一个对象,对象中可以设置多个属性,如下:
- test属性:用于对 resource(资源)进行匹配的,通常会设置成正则表达式。
- use属性:对应的值是一个数组:[UseEntry], UseEntry是一个对象,可以通过对象的属性来设置一些其他属性:
loader:必须有一个 loader属性,对应的值是一个字符串;
options:可选的属性,值是一个字符串或者对象,值会被传入到loader中;
query:目前已经使用options来替代;
写法如下,其中写法一、二是简洁的写法,写法三是完整的写法。
认识style-loader
我们已经可以通过css-loader来加载css文件了,但是你会发现这个css在我们的代码中并没有生效(页面没有效果)这是为什么呢?
因为css-loader只是负责将.css文件进行解析,并不会将解析之后的css插入到页面中,如果我们希望再完成插入style的操作,那么我们还需要另外一个loader,就是style-loader。
安装style-loader:
npm install style-loader -D
配置style-loader
那么我们应该如何使用style-loader?
在配置文件中,添加style-loader。注意:因为loader的执行顺序是从右向左(或者说从下到上,或者说从后到前的),所以我们需要将style�loader写到css-loader的前面。
重新执行编译npm run build,可以发现打包后的css已经生效了。
如何处理less文件?
在我们开发中,我们可能会使用less、sass、stylus的预处理器来编写css样式,效率会更高。那么,如何可以让我们的环境支持这些预处理器呢?
首先我们需要确定,less、sass等编写的css需要通过工具转换成普通的css,比如我们编写如下的less样式:
less工具处理
我们可以使用less工具来完成它的编译转换:
npm install less -D
执行如下命令,将title.less转成title.css。
npx lessc ./src/css/title.less title.css
less-loader处理
但是在项目中我们会编写大量的css,它们如何可以自动转换呢?
这时候我们就可以使用less-loader,来自动使用less工具转换less到css。
npm install less-loader -D
配置webpack.config.js:
上面顺序不能乱,因为要先将less转成css,再插入到项目中。执行npm run build,less就可以自动转换成css,并且页面也会生效了。
认识PostCSS工具
PostCSS是一个通过JavaScript来转换样式的工具,这个工具可以帮助我们进行一些CSS的转换和适配,比如自动添加浏览器前缀、css样式的重置,但是实现这些功能,我们需要借助于PostCSS对应的插件。
命令行使用postcss
当然,我们能不能也直接在终端使用PostCSS呢?也是可以的,但是我们需要单独安装一个工具postcss-cli。
我们可以安装一下它们:postcss、postcss-cli。
npm install postcss postcss-cli -D
我们编写一个需要添加前缀的css。https://autoprefixer.github.io/,我们可以在左边的网站中查询一些添加css属性的样式。
因为我们需要添加前缀,所以要安装autoprefixer插件:
npm install autoprefixer -D
直接使用postcss工具,并且自动使用autoprefixer插件:
npx postcss --use autoprefixer -o end.css ./src/css/style.css
转化之后的css样式如下:
postcss-loader
真实开发中我们必然不会直接使用命令行工具来对css进行处理,而是可以借助于构建工具,在webpack中使用postcss就是使用postcss-loader来处理。
我们来安装postcss-loader:
npm install postcss-loader -D
我们修改加载css的loader:(配置文件过多,只给出一部分)。
注意:因为postcss需要有对应的插件才会起效果,所以我们需要配置它的插件:autoprefixer。
单独的postcss配置文件
当然,我们也可以将这些配置信息放到一个单独的文件中进行管理,在根目录下创建postcss.config.js
,写如下代码:
这样我们直接指定"postcss-loader"就可以了,就不用写这么多乱的代码了。
use: [
// {loader: "css-loader"}
"style-loader",
"css-loader",
"postcss-loader"
// {
// loader: "postcss-loader",
// options: {
// postcssOptions: {
// plugins: [
// require("autoprefixer")
// ]
// }
// }
// }
]
具体流程就是先看看有没有配置信息,如果没有,就把postcss.config.js
里面导出的对象当成配置信息。
postcss-preset-env
事实上,在配置postcss-loader时,我们配置插件并不会配置autoprefixer,我们会使用另外一个插件:postcss-preset-env,它也是一个postcss的插件,而且更强大。
它可以帮助我们将一些现代的CSS特性,转成大多数浏览器认识的CSS,并且会根据目标浏览器或者运行时环境添加所需的polyfill,也包括会自动帮助我们添加autoprefixer,所以相当于已经内置了autoprefixer。
首先,我们需要安装postcss-preset-env:
npm install postcss-preset-env -D
之后,我们直接修改掉之前的autoprefixer即可:
而且这个插件在使用的时候可以直接传入字符串,如下:
补充:当然我们也可以将css和less的匹配规则写到一起,如下:
{
test: /\.(css|less)$/,
use: [
"style-loader",
"css-loader",
"postcss-loader",
"less-loader"
]
}
网友评论