webpack
认识webpack
webpack是什么?
webpack官方解释
webpack is a static module bundler for modern JavaScript applications.
为现代化的JavaScript应用程序的静态的模块化打包工具
为什么需要webpack?
前端开发越来越复杂。
比如开发中需要通过模块化的方式来开发
使用一些高级特性来加快我们的开发效率或安全性,比如ES6、TypeScript开发脚本逻辑,通过sass、less等方式编写css代码。
还希望实时的监听文件的变化且反映到浏览器上,提高开发的效率
开发完后还需要将代码进行压缩、合并以及其他相关的优化
等等
但我们实际开发过程中,并不需要去考虑这些问题。
我们往往直接用三大框架进行开发,而这三大框架的创建过程都是借助于脚手架(CLI)的。
脚手架依赖于webpack。
Vue-CLI、create-react-app、Angular-CLI都是基于webpack来帮助我们支持模块化、less、TypeScript、打包优化等。
Vue项目加载的文件有哪些呢?
JavaScript的打包
将ES6转换成ES5语法
TypeScript转成JavaScript
Css的处理
CSS文件模块的加载、提取
Less、Sass等预处理器处理
资源文件img、font的加载
HTML资源的处理:打包html资源文件
处理vue项目的SFC文件.vue文件
安装webpack
1.在安装webpack之前,需要先安装nodejs
nodejs官网:下载LTS版本即可。
nodejs安装好,我们就可以使用npm工具了。
通过在控制台查看nodejs版本来确定是否安装成功。
2.使用npm命令安装webpack webpack-cli
(以下演示的是全局安装,而在开发中,我们往往是局部安装webpack)
在控制台操作即可
npm install webpack webpack-cli -g #全局安装
注意:以上命令,要以管理员的身份
打开命令提示符
那么,我们为什么还要安装webpack-cli呢?
执行webpack命令,就会执行node_modules/.bin下的webpack;
webpack在执行时是依赖webpack-cli的,没有安装就会报错;
而webpack-cli中代码执行时又利用webpack进行编译和打包。所以,安装webpack时同时需要安装webpack-cli。
但是,我们在使用第三方脚手架时并没有使用webpack-cli,而是类似于自己的vue-service-cli的东西。
webpack的简单使用
我们创建一个新项目,项目结构如下。项目根目录下有src文件夹和index.html文件。
format.js
const priceFormat = function() {
return "¥99.88";
}
// CommonJS的导出
module.exports = {
priceFormat
}
math.js
// ES Module
export function sum(num1, num2) {
return num1 + num2;
}
index.js
import { sum } from "./js/math";
const { priceFormat } = require("./js/format");
console.log(sum(20, 30));
console.log(priceFormat());
index.html中引入js
<script src="./src/index.js" type="module"></script>
首先,我们需要知道浏览器是不支持CommonJS的,而我们开发中经常这么写,以上代码浏览器不能运行,我们该怎么办呢?
我们可以使用webpack对项目进行打包。打包后新产生dist文件夹,我们引入相关文件,就可以运行了。
那怎么对写好的项目打包呢?
很简单,我们cd进入项目根路径,使用webpack
命令(这种表示是使用全局webpack),这样项目就被打包好了,这个时候我们改一下index.html引入的js文件路径,项目就可以正常在浏览器运行了。
<script src="./dist/main.js"></script>
在此,有个很好用的插件,Live Server,可以帮助我们很快运行项目并实时刷新。
webpack入口文件
webpack是如何确定我们的入口呢?
因为执行webpack
时,webpack会查找当前目录下的src/index.js来作为入口。没有src/index.js文件,会报错。
我们有两种方法:
第一种,把入口文件写到src/index.js下。
第二种,通过配置指定的入口和出口。
npx webpack --entry ./src/main.js --output-path ./build
webpack的局部方式打包
我们以上项目运行是通过全局webpack进行打包的。
但是,在真实开发中,全局webpack往往会带来很多问题,我们每个项目所依赖的webpack版本不同,而全局安装的webpack如果与项目依赖的webpack版本不一致会导致兼容性等问题。
在开发项目中,往往是采用局部安装webpack。
步骤:
1.创建package.json文件,用于管理项目的信息、库依赖等
npm init
执行此命令,将生成package.json文件
{
"name": "00my_test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
2.安装局部webpack
-D
和--save-dev
:表示开发时依赖
npm install webpack webpack-cli -D
或者
npm install webpack webpack-cli --save-dev
执行后,项目目录下会自动创建node_modules文件夹
3.打包
我们有两种方式(这两种都是局部webpack方式)
使用webpack
命令是全局方式
第一种,npx webpack
第二种,在package.json中创建scripts脚本,执行脚本npm run build
打包
"scripts": {
"build": "webpack"
}
webpack配置文件
指定配置文件
在项目根目录下创建webpack.config.js文件,这个配置文件的名字不能随便起。
当然,想改名也是有办法的。通过webpack --config
来指定对应配置文件名称
在package.json中
注意:package.json中不允许写注释
webpack.config.js配置项目入口出口文件
const path = require('path');
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "./build"),
filename: "bundle.js"
}
}
注意:
1.用module.exports(CommonJS方式)导出一个对象
2.output的path写绝对路径,不能写相对路径
用node的path模块,path.resolve帮助我们对路径进行拼接。__dirname
为项目根路径
webpack依赖图
我们来思考一下,我们配置了入口文件index.js。但是,为什么src/math.js和src/format.js也能被打包呢?它们也没进行配置啊?
我们上面的案例,之所以能够打包成功,是因为入口文件index.js中包含了src/math.js和src/format.js的依赖。如果不写这两个js文件的导入,那么,项目就无法对这两个文件打包。
//index.js入口文件
import { sum } from "./js/math";
const { priceFormat } = require("./js/format");
console.log(sum(20, 30));
console.log(priceFormat());
这就涉及到webpack的依赖关系图了。
webpack在对项目进行打包时,会根据命令或者配置文件找到入口文件;
从入口开始,会生成一个依赖关系图,这个关系图会包含应用程序中所需的所有模块(.js .css 图片等)
然后,遍历图结构,打包一个个模块(根据文件的不同使用不同的loader来解析)
总而言之,要想某些文件能被打包,需要与入口文件产生直接或间接的依赖关系。
直接:文件直接在入口文件index.js中导入
间接:比如在math.js中导入我们需要的css文件,而math.js导出到index.js中
Loader
loader配置方式
即在webpack.config.js中写明配置信息。
rules属性对应一个数组:[rules]
数组中存放的是一个个rule对象。
对象可以有多个属性
test属性:对资源进行匹配,通常用正则表达式
use属性:对应值一个数组,loader是必有的属性
loader属性:rule.use的简写
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "./build"),
filename: "bundle.js"
},
//配置loader
module: {
rules: [
// 匹配css的rule对象
{
test: /\.css$/, //正则表达式
// 1.loader的写法(语法糖)
// loader: "css-loader"
use: [
"style-loader",
"css-loader",
"postcss-loader"
]
},
// 匹配less的rule对象
{
test: /\.less$/,
use: [
"style-loader",
"css-loader",
"less-loader"
]
},
//css和less可以写到一个rule对象中
// {
// test: /\.(less|css)$/,
// use: [
// "style-loader",
// "css-loader",
// "less-loader"
// ]
// }
]
}
}
css-loader
对以上代码进行webpack打包,无法正常执行。提示我们缺少loader,我们需要loader加载css文件,最常用的是css-loader。
那么,我们需要安装css-loader
npm install css-loader -D
接着,使用它,有三种方式:内联方式、CLI方式、配置方式。
推荐使用配置方式。
在webpack.config.js中
module: {
rules: [
{
test: /\.css$/, //正则表达式
// 2.完整的写法
use: [
// {loader: "css-loader"}
"css-loader"
]
}
]
}
style-loader
但是,我们发现代码仍然没有生效。为什么呢?
因为css-loader只是负责将.css文件进行解析,并不会将解析之后的css插入到页面中
如果我们希望再完成插入style的操作,我们还需要另外一个loader,就是style-loader
1.安装style-loader
npm install style-loader -D
2.按照同样的方法去配置style-loader
但是要注意:use在加载loader的时候,是从下到上的。
我们需要将style-loader写到css-loader上面
less-loader
1.安装less-loder
npm install less-loader -D
自动使用less工具(lessc)转换less到css
2.webpack.config.js
{
test: /\.less$/,
use: [
"style-loader",
"css-loader",
"less-loader"
]
}
执行npm run build
,less就会自动转成css,且页面也会生效显示了。
PostCSS
什么是PostCSS?
一个通过JavaScript来转换样式的工具
帮助我们进行一些CSS的转换和适配,比如自动添加浏览器前缀、css样式的重置
但实现这些功能,需要借助PostCSS对应的插件
如何使用PostCSS呢?
在webpack中使用postcss就是使用postcss-loader来处理的
1.安装postcss-loader
npm install postcss-loader -D
2.postcss需要对应插件才会起效果,我们需要配置它的plugin
3.有两种方式实现配置
以下例子使用postcss的postcss-preset-env插件
postcss-preset-env插件帮助我们实现一些现代的CSS特性,转成大多数浏览器认识的CSS,并会根据目标浏览器或者运行时环境添加所需的polyfill
第一种 webpack.config.js中配置
use: [
"style-loader",
"css-loader",
"postcss-loader"
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
require("postcss-preset-env")
]
}
}
}
]
第二种:单独的postcss配置文件
1.postcss.config.js文件
module.exports = {
plugins: [
require("postcss-preset-env")
]
}
2.webpack.config.js
use: [
"style-loader",
"css-loader",
"postcss-loader"
]
总结
css-loder:解析.css文件
style-loader:插入style操作
less-loader:将less转成css
postcss-loader:进行css的转换和适配。如自动添加浏览器前缀(使用postcss-preset-env插件)、css样式的重置
以上笔记参考coderwhy老师的Vue3和TypeScript。
老师讲课链接:课程链接