一. 认识webpack工具
1. 内置模块path
path模块用于对路径和文件进行处理,提供了很多好用的方法- 我们知道在
Mac OS、Linux和`window上的路径时不一样的window上会使用\或者\\来作为文件路径的分隔符,当然目前也支持/- 在
Mac OS、Linux的Unix操作系统上使用/来作为文件路径的分隔符
- 那么如果我们在
window上使用\来作为分隔符开发了一个应用程序,要部署到Linux上面应该怎么办呢?- 显示路径会出现一些问题
- 所以为了屏蔽他们之间的差异,在开发中对于路径的操作我们可以使用
path模块,node会根据操作系统自动处理对应的路径
- 可移植操作系统接口(英语:
Portable Operating System Interface,缩写为POSIX)Linux和Mac OS都实现了POSIX接口Window部分电脑实现了POSIX接口
2. path常见的API
从路径中获取信息
path.dirname(filepath):获取文件的父文件夹__dirname: 当前模块的所在目录名,全局可使用,但实际并不是全局对象
path.basename(filepath):获取文件名path.extname(filepath):获取文件扩展名__filename: 当前模块的文件名
jsconst path = require('path') const filepath = 'C://abc/cba/nba.txt' console.log(path.dirname(filepath)) // C://abc/cba console.log(path.basename(filepath)) // nba.txt console.log(path.extname(filepath)) // .txt路径的拼接:
path.join(...paths)- 如果我们希望将多个路径进行拼接,但是不同的操作系统可能使用的是不同的分隔符
- 这个时候我们可以使用
path.join函数
jsconst path = require('path') const path1 = "/abc/cba" const path2 = "../aaa/bbb/ccc.txt" const path3 = "./ddd/eee.js" console.log(path.join(path1, path2)) // \abc\aaa\bbb\ccc.txt console.log(path.join(path1, path3)) // \abc\cba\ddd\eee.js console.log(path.join(path2, path3)) // ..\aaa\bbb\ccc.txt\ddd\eee.js console.log(path.join(path3, path2)) // ddd\aaa\bbb\ccc.txt拼接绝对路径:
path.resolve()path.resolve方法会把一个路径或路径片段的序列解析为一个绝对路径- 给定的路径的序列是从右往左被处理的,后面每个
path被依次解析,直到构造完成一个绝对路径,\绝对路径,指当前文件所作的根目录 - 如果在处理完所有给定
path的段之后,还没有生成绝对路径,则使用当前工作目录 - 生成的路径被规范化并删除尾部斜杠,零长度
path段被忽略 - 如果没有
path传递段,path.resolve()将返回当前工作目录的绝对路径(当前模块所在的目录名)
jsconst path = require('path') const path1 = "/abc/cba" const path2 = "../aaa/bbb/ccc.txt" const path3 = "./ddd/eee.js" // 注意:当前文件所在目录:C:\Users\23634\Desktop\learn\ console.log(path.resolve(path1, path2, path3)) // C:\abc\aaa\bbb\ccc.txt\ddd\eee.js console.log(path.resolve(path3)) // C:\Users\23634\Desktop\learn\ddd\eee.js console.log(path.resolve('./hello/', '')) // C:\Users\23634\Desktop\learn\hello console.log(path.resolve()) // C:\Users\23634\Desktop\learn
3.在webpack中的使用
在
webpack中获取路径或者起别名的地方也可以使用
4.认识webpack
- 事实上随着前端的快速发展,目前前端的开发已经变的越来越复杂了:
- 比如开发过程中我们需要通过模块化的方式来开发
- 比如也会使用一些高级的特性来加快我们的开发效率或者安全性,比如通过
ES6+、TypeScript开发脚本逻辑,通过sass、less等方式来编写css样式代码 - 比如开发过程中,我们还希望实时的监听文件的变化来并且反映到浏览器上,提高开发的效率
- 比如开发完成后我们还需要将代码进行压缩、合并以及其他相关的优化等…
- 但是对于很多的前端开发者来说,并不需要思考这些问题,日常的开发中根本就没有面临这些问题:
- 这是因为目前前端开发我们通常都会直接使用三大框架来开发:
Vue、React、Angular - 但是事实上,这三大框架的创建过程我们都是借助于脚手架(
CLI)的 - 事实上
Vue-CLI、create-react-app、Angular-CLI都是基于webpack来帮助我们支持模块化、less、TypeScript、打包优化等的
- 这是因为目前前端开发我们通常都会直接使用三大框架来开发:
5.脚手架依赖webpack
- 事实上我们上面提到的所有脚手架都是依赖于
webpack的:

6.Webpack到底是什么呢?
我们先来看一下官方的解释:

webpack是一个静态的模块化打包工具,为现代的JavaScript应用程序我们来对上面的解释进行拆解:
- 打包
bundler:webpack可以将帮助我们进行打包,所以它是一个打包工具 - 静态的
static:这样表述的原因是我们最终可以将代码打包成最终的静态资源(部署到静态服务器) - 模块化
module:webpack默认支持各种模块化开发,ES Module、CommonJS、AMD等 - 现代的
modern:我们前端说过,正是因为现代前端开发面临各种各样的问题,才催生了webpack的出现和发展
- 打包
7.Vue项目加载的文件有哪些呢?
JavaScript的打包:- 将
ES6转换成ES5的语法 TypeScript的处理,将其转换成JavaScript
- 将
CSS的处理:CSS文件模块的加载、提取Less、Sass等预处理器的处理
- 资源文件
img、font:- 图片
img文件的加载 - 字体
font文件的加载
- 图片
HTML资源的处理:- 打包
HTML资源文件
- 打包
- 处理
vue项目的SFC文件.vue文件
8.Webpack的使用前提
webpack的官方文档是https://webpack.js.org/webpack的中文官方文档是https://webpack.docschina.org/DOCUMENTATION:文档详情,也是我们最关注的
Webpack的运行是依赖Node环境的,所以我们电脑上必须有Node环境- 所以我们需要先安装
Node.js,并且同时会安装npm,也可以使用nvm或者n来管理Node版本
- 所以我们需要先安装
9.Webpack的安装
webpack的安装目前分为两个:webpack、webpack-cli(webpack4开始,安装webpack需要同时安装webpack-cli,此工具用于在命令行中运行webpack)那么它们是什么关系呢?
- 执行
webpack命令,会执行node_modules下的.bin目录下的webpack webpack在执行时是依赖webpack-cli的,如果没有安装就会报错webpack-cli是在命令行里使用webpack必须要用的东西,因为其作用是能识别命令行- 而
webpack-cli中代码执行时,才是真正利用webpack进行编译和打包的过程 - 所以在安装
webpack时,我们需要同时安装webpack-cli(第三方的脚手架事实上是没有使用webpack-cli的,而是类似于自己的vue-service-cli的东西)

- 执行
二.webpack基本打包
1. Webpack的默认打包(重点)
我们可以通过
webpack进行打包,之后运行打包之后的代码在目录下直接执行
webpack命令bashnpx webpack # 或 webpack
生成一个
dist文件夹,里面存放一个main.js的文件,就是我们打包之后的文件:- 这个文件中的代码被压缩和丑化了
- 另外我们发现代码中依然存在
ES6的语法,比如箭头函数、const等,这是因为默认情况下webpack并不清楚我们打包后的文件是否需要转成ES5之前的语法,后续我们需要通过babel来进行转换和设置
我们发现是可以正常进行打包的,但是有一个问题,
webpack是如何确定我们的入口的呢?事实上,当我们运行
webpack时,webpack默认会查找当前目录下的src/index.js作为入口所以,如果当前项目中没有存在
src/index.js文件,那么会报错导入时如果省略后缀名,
webpack本身也会帮我们添加文件后缀名当然,我们也可以通过
cli参数中来指定入口和出口bash# --entry 入口地址 # --output-path 打包文件所在文件夹路径 # --output-filename 打包文件名称 npx webpack --entry ./src/main.js --output-path ./build --output-filename aaa.js--output-path:配置打包后的文件夹路径--output-filename:配置打包后的文件夹下面的源文件名称
也可以选择在
webpack配置文件中配置jsconst path = require('path') // const curDir = path.resolve() // console.log(curDir + '\\bundle') module.exports = { entry: './src/main.js', output: { filename: 'aaa.js', // path: curDir + '\\bundle' // path: path.resolve('./bundle') path: path.resolve(__dirname, './bundle') // 必须是绝对路径 } }webpack的配置文件webpack.config.js文件名是固定的,而webpack是基于node运行的,跑在node的环境下,所以这个模块文件只能使用node的CommonJS的模块化,不能使用别的模块化执行
npx webpack,默认会去当前目录下寻找配置文件webpack.config.js如果需要修改指定配置文件名,使用
npx webpack --config wk.config.js,或者package.json文件中配置scripts命令
2.创建局部的webpack
前面我们直接执行
webpack命令使用的是全局的webpack,如果希望使用局部的可以按照下面的步骤来操作第一步:创建
package.json文件,用于管理项目的信息、库依赖等jsnpm init -y // 自动生成默认配置信息 npm init // 手动设置配置信息第二步:安装局部的
webpack(webpack4.x开始,这两个都需要安装)bashnpm i webpack webpack-cli -D // webpack属于开发依赖第三步:使用局部的
webpackbash# 一般包都是需要使用 npx + 包 命令来搭配使用的,正常是不会去当前目录中的子目录中查找node_modules文件中对应的包 npx webpack # webpack比较特殊,可以省略npx,会去当前目录的子目录中查找node_modules文件中对应的包 webpack第四步:在
package.json中创建scripts脚本,执行脚本打包即可js"scirpt": { "build": "webpack" // npm run build }
三. webpack配置文件
1.webpack.config.js配置文件
- 在通常情况下,
webpack需要打包的项目是非常复杂的,并且我们需要一系列的配置来满足要求,默认配置必然是不可以的 - 我们可以在根目录下创建一个
webpack.config.js文件,来作为webpack的配置文件:

2.指定配置文件
- 但是如果我们的配置文件并不是
webpack.config.js的名字,而是其他的名字呢?- 比如我们将
webpack.config.js修改成了wk.config.js - 这个时候我们可以通过
--config来指定对应的配置文件
- 比如我们将
- 但是每次这样执行命令来对源码进行编译,会非常繁琐,所以我们可以在
package.json中增加一个新的脚本:

四. 编写和打包CSS文件
1.Webpack的依赖图
webpack到底是如何对我们的项目进行打包的呢?- 事实上
webpack在处理应用程序时,它会根据命令或者配置文件找到入口文件 - 从入口开始,会生成一个 依赖关系图,这个依赖关系图会包含应用程序中所需的所有模块(比如
js文件、css文件、图片、字体等) - 然后遍历图结构,打包一个个模块(根据文件的不同使用不同的
loader来解析,webpack默认只会对js文件进行打包,内置功能)

- 事实上
2.编写案例代码
我们创建一个
component.js- 通过
JavaScript创建了一个元素,并且希望给它设置一些样式

- 通过
3.css-loader的使用
上面的错误信息告诉我们需要一个合适的
loader来处理这个css文件,但是loader是什么呢?loader可以用于对模块的源代码进行转换- 我们可以将
css文件也看成是一个模块,我们是通过import来加载这个模块的- 如果有一个模块只是为了引入,而没有导出任何的东西,这样就表示该模块加入到依赖图中了,这里是可以不写
from的
- 如果有一个模块只是为了引入,而没有导出任何的东西,这样就表示该模块加入到依赖图中了,这里是可以不写
- 在加载这个模块时,
webpack其实并不知道如何对其进行加载,我们必须制定对应的loader来完成这个功能
那么我们需要一个什么样的
loader呢?- 对于加载
css文件来说,我们需要一个可以读取css文件的loader - 这个
loader最常用的是css-loader
- 对于加载
css-loader的安装:jsnpm i css-loader -D // loader打包时(开发阶段)依赖
4.css-loader的使用方案
如何使用这个
loader来加载css文件呢?有三种方式:- 内联方式
CLI方式(webpack5中不再使用)- 配置方式
内联方式:内联方式使用较少,因为不方便管理
在引入的样式前加上使用的
loader,并且使用!分割jsimport "css-loader!./css/style.css"
CLI方式- 在
webpack5的文档中已经没有了--module-bind - 实际应用中也比较少使用,因为不方便管理
- 在
5.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来替代
- 传递字符串(如:
use: [ 'style-loader' ])是loader属性的简写方式(如:use: [ { loader: 'style-loader'} ])
loader属性:Rule.use: [ { loader } ]的简写
6.Loader的配置代码
const path = require('path')
module.exports = {
entry: './src/main.js',
output: {
filename: 'aaa.js',
path: path.resolve(__dirname, './bundle')
},
module: {
rules: [
{
test: /\.css$/, // 告诉webpack匹配什么文件
use: [ // use多个loader使用顺序:从下往上 从右往左的
{ loader: 'style-loader' },
{ loader: 'css-loader' }
],
// 简写一: 如果loader只有一个,可以省略use,直接写在外面
loader: "css-loader",
// 简写二: 多个loader不需要其他属性时, 可以直接写loader字符串形式
use: [
"style-loader",
"css-loader"
]
}
]
}
}7.认识style-loader
我们已经可以通过
css-loader来加载css文件了- 但是你会发现这个css在我们的代码中并没有生效(页面没有效果)
这是为什么呢?
- 因为**
css-loader只是负责将.css文件进行解析,并不会将解析之后的css插入到页面中** - 如果我们希望再完成插入
style的操作,那么我们还需要另外一个loader,就是style-loader
- 因为**
安装
style-loader:jsnpm i style-loader -D // loader打包时(开发阶段)依赖
8.配置style-loader
那么我们应该如何使用
style-loader:- 在配置文件中,添加
style-loader - 注意:因为**
loader的执行顺序是从右向左(或者说从下到上,或者说从后到前的)**,所以我们需要将style-loader写到css-loader的前面
jsuse: [ // use多个loader使用顺序:从下往上 从右往左的 从后往前 { loader: 'style-loader' }, { loader: 'css-loader' } ]- 在配置文件中,添加
重新执行编译
npm run build,可以发现打包后的css已经生效了:- 当前目前我们的
css是通过页内样式的方式添加进来的 - 后续我们也会讲如何将
css抽取到单独的文件中,并且进行压缩等操作
- 当前目前我们的
五. 编写和打包less文件
1.如何处理less文件?
在我们开发中,我们可能会使用
less、sass、stylus等预处理器来编写cs样式,效率会更高那么,如何可以让我们的环境支持这些预处理器呢?
- 首先我们需要确定,
less、sass等编写的css需要通过工具转换成普通的css
- 首先我们需要确定,
比如我们编写如下的
less样式:less@fontSize: 30px; @fontWeight: 700; .content { font-size: @fontSize; font-weight: @fontWeight; }
2.Less工具处理
我们可以使用
less工具来完成它的编译转换:jsnpm i less -D执行如下命令:
jsnpx lessc ./src/css/title.less title css
3.less-loader处理
但是在项目中我们会编写大量的
css,它们如何可以自动转换呢?这个时候我们就可以使用
less-loader,来自动使用less工具转换less到cssless-loader依赖less,所以less的包也会被安装
jsnpm i less-loader -D
配置
webpack.config.jsjs{ test: /\.less$/, use: [ "style-loader", "css-loader", "less-loader" ] // less-loader先转换成css,然后css-loader处理... }
六.postcss工具处理CSS
1.认识PostCSS工具
use-select:none;让用户无法选中该元素,但是这个属性有一定兼容性问题,所以需要用到postcss来帮助我们判断属性是否需要添加浏览器前缀来做兼容- 什么是
PostCSS呢?PostCSS是一个通过JavaScript来转换样式的工具- 这个工具可以帮助我们进行一些
CSS的转换和适配,比如自动添加浏览器前缀、css样式的重置 - 但是实现这些功能,我们需要借助于
PostCSS对应的插件
- 如何使用
PostCSS呢?主要就是两个步骤:- 第一步:查找
PostCSS在构建工具中的扩展,比如webpack中的postcss-loader - 第二步:选择可以添加你需要的
PostCSS相关的插件
- 第一步:查找
2.postcss-loader
我们可以借助于构建工具:
在
webpack中使用postcss就是使用postcss-loader来处理的我们来安装
postcss-loader:jsnpm i postcss-loader -D // 开发打包时依赖
我们修改加载
css的loader:(配置文件已经过多,给出一部分了)- 注意:因为**
postcss需要有对应的插件才会起效果**,所以我们需要配置它的plugin
- 注意:因为**
3.单独的postcss配置文件
因为我们需要添加前缀,所以要安装
autoprefixer:jsnpm i autoprefixer -D我们可以将这些配置信息放到一个单独的文件中进行管理:
在项目的根目录下创建
postcss.config.jsjsmodule.exports = { plugins: [ 'autoprefixer' // 在使用某些postcss插件时,也可以直接传入字符串 // require('autoprefixer') ] }
4.postcss-preset-env
事实上,在配置
postcss-loader时,我们配置插件并不需要使用autoprefixer我们可以使用另外一个插件:
postcss-preset-envpostcss-preset-env也是一个postcss的插件- 它可以帮助我们将一些现代的
CSS特性,转成大多数浏览器认识的CSS,并且会根据目标浏览器或者运行时环境添加所需的polyfill - 也包括会自动帮助我们添加
autoprefixer(所以相当于已经内置了autoprefixer)
首先,我们需要安装
postcss-preset-envjsnpm i postcss-preset-env -D之后,我们直接修改掉之前的
autoprefixer即可:jsmodule.exports = { plugins: [ // 'autoprefixer' // 在使用某些postcss插件时,也可以直接传入字符串 'postcss-preset-env' // 可以帮助十六进制颜色转换为rgba ] }postcss-loader和less-loader没有前后顺序要求
