目标:
- 能处理css,less文件,解决css的浏览器兼容性配置
- 能处理字体文件
- 能处理图片文件
- 能处理js降级问题
在webpack看来 一切皆模块,图片,样式文件,js文件… 。 但是webpack默认只能处理js模块,对于非js的内容它就需要一些帮手来处理了。这些帮手就是loader。
webpack 可以使用 loader 来预处理文件。这允许你打包除 JavaScript 之外的任何静态资源。
处理css文件
下面,我们来讨论如何处理.css文件。
创建.css文件
在src目录下,再次创建一个css目录
|-src
|-src/css
|--------public.css
|--------style.css
src/css/public.css的内容如下
body,html{
padding:0;
font-size:14px;
}
src/css/style.css的内容如下
@import "public.css";
div {
border:4px solid #ccc;
width: 50%;
height: 200px;
margin:30px auto;
box-shadow: 3px 3px 3px #ccc;
background-color: #fff;
text-align: center;
}
说明:
- @import语句用来导入另一个css文件。
如果希望在.html文件中使用style.css样式,我们以前只学习过一种方式:直接在.html中通过link的方式来引入 。
那如果在js中引入了css会怎么样呢?
在.js中导入css
下面,我们修改自已的main.js,在 src/js/main.js中,引入css。
// nodejs中的模块化
const { updateDom } = require('./tool')
+ import '../css/style.css'
updateDom ('app','index.html')
log('test')
再次,打包代码,会报错。
ERROR in ./src/css/style.css 1:0
Module parse failed: Unexpected character '@' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> @import "public.css";
| div {
| padding:20px;
@ ./src/js/main.js 4:0-26
上面报错的原因是:webpack把.css文件内容当作了js代码来运行,那当然会报错了。所以,解决方法是安装相应的loader来处理。
安装并使用css-loader
对于所有的loader的使用,其基本步骤是一致的,分成两步:
-
- 安装loader包
-
- 配置webpack.config.js中的module
安装
npm i css-loader -D
--------------------
+ css-loader@4.1.1
added 16 packages from 51 contributors in 14.718s
7 packages are looking for funding
它也是开发依赖。
在配置文件中使用
修改webpack.config.js文件,添加modules
const path = require('path')
module.exports = {
mode: 'development',
entry:'./src/js/main.js',
output:{
path:path.resolve(__dirname, './build'),
filename:'bundle.js'
},
+ module:{ // 处理非js模块
+ rules:[ // 规则
+ {
+ test: /\.css$/, // 正则测试
+ use: ['css-loader'] // loader
+ }
+ ]
+ }
}
再次打包
它不会报错。但是,页面上也并没有出现样式的效果。打包之后的文件中并没有包含css代码。
安装并使用style-loader
如果我们希望样式生效,最终在.html文件中有两种情况:
- 有style标签
- 有link标签
而css-loader只是能让你在.js中通过import来引入.css,如果你希望引入的css代码最终以style标签的方式插入到html页面中,则还需要安装一个loader:style-loader
安装
npm i style-loader -D
---------------
+ style-loader@1.2.1
added 4 packages from 6 contributors in 13.086s
8 packages are looking for funding
run `npm fund` for details
配置
// node 中的核心模块
const path = require('path')
// __dirname: 全局变量,指向当前目录绝对地址
// console.log(__dirname)
// // path.join是拼接
// console.log( path.join(__dirname, 'dist123') )
// 1. 导出一个配置
// 2. mode, entry, output...... 都是webpack这个工具约定的配置名称
// 每一项都有自己的作用
// 3. 学习webpack 就是学习webpac.config.js中的配置项的使用方式
module.exports = {
// mode: 'production',
mode: 'development',
// devtool: 'source-map',
// devtool: 'inline-source-map',
// 入口
// 默认入口:src/index.js
entry: './src/js/index.js',
// 出口
// 默认出口: dist/main.js
output: {
filename: 'main.js',
// path: 必须是一个绝对路径
path: path.join(__dirname, 'build')
},
module: {
rules: [
// 每一个对象就是一条规则.
// test: 匹配
// use: 对匹配到的模块采用对应的loader
{
test: /\.css$/, // 正则匹配 .css文件
// 匹配成功后(从后向前;从右到左)
// 1. 先用css-loader去加载.css文件
// 2. 再用style-loader把样式以style标签的方式嵌入到html中
use: ['style-loader', 'css-loader']
}
]
}
}
Tip: 在有多个loader的情况下,use数组中的loader执行顺序是从右到左的过程。即:
- 先用css-loader来处理css
- 再用style-loader把css代码插入到html中的style标签中。
打包查看效果
index.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>index</title>
<!-- <link rel="stylesheet" href="./css/style.css"> -->
</head>
<body>
<div id="app">
</div>
<!-- 引入两个js文件 -->
<!-- <script src="./index.js"></script>
<script src="./tool.js"></script> -->
<!-- 引入打包之后的js -->
<script src="../build/main.js"></script>
</body>
</html>
现在就能看到css的效果了 。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CyA3T8Jn-1603365751269)(asset/image-20200731143422794.png)]
原理是:
- bundle.js中有一些js代码,它在运行时,会自动在.html文件中追加style标签,并输出样式。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uF2nJvhN-1603365751271)(asset/image-20200603143508746.png)]
拓展
你可以分析打包之后代码,来验证style-loader的工作原理。在main.js中,可以找到类似如下的代码:
eval("var api = __webpack_require__(/*! ../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ \"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js
再去node_modules\style-loader\dist\runtime\injectStylesIntoStyleTag.js
找下insertStyleElement
这个方法,你就可以发现这个过程。
loader使用小结
-
在webpack看来,一切皆模块: 每一个文件都是一个模块。
-
webpack默认只能处理json和js模块,对于其它的模块它需要对应的loader来处理
-
loader的基本使用是:
- 安装Loader (npm 包)
- 配置module中的rules:用loader来处理对应类型的文件
处理less文件
目标:在项目中支持使用less来写css代码。
改进案例
创建less文件
在src目录的css目录下创建 index.less,则内容如下:
@import "style.css";
body{
div {
padding:50px;
}
}
在.js中引用.less
在src/js/main.js文件中引入less
// nodejs中的模块化
const { updateDom } = require('./tool')
// es6中的模块化
import {log} from './tooles6'
- import '../css/style.css'
+ import '../css/index.less'
updateDom ('app','index.html')
log('test')
安装并配置loader包
less less-loader
参考官网
npm i less-loader less -D
-------------------------
+ less@3.11.2
+ less-loader@6.1.0
added 50 packages from 123 contributors in 23.883s
- less 用来把less–>css
- less-loader用来加载less文件。
配置模块
在rules中添加一个配置,专门针对less文件。
/**
1. 要放在项目的根目录下。
2. 在npx webpack打包时,会自动去找这个文件,并运行其中的
代码。如果找不到,则进入零配置模式 ---- 采用一些默认配置。
*/
// nodejs中一个核心模板
console.log('打包文件....')
const path = require('path')
module.exports = {
// mode: 'development',
mode: 'production',
devtool: 'cheap-module-source-map',
entry: './src/js/main.js', // 入口
output: {
// 拼接一个绝对路由
path: path.join(__dirname, './build'),
filename: 'bundle.js'
},
// 非js模块要如何处理? 在module中定义
module: {
// 规则
rules: [
{
test: /\.css$/, // 如果这个模块以css结尾
// 如果在打包的过程遇到了.css,则:
// 1. 先用css-loader读出内容
// 2. style-loader把读出的内容以style标签的格式
// 附加在.html文件上
use: ['style-loader', 'css-loader'] // 设置要处理的loader
},
{
test: /\.less$/, // 如果这个模块以less结尾
// 如果在打包的过程遇到了.less,则:从右向左
// 1. 先用less-loader 读出内容,转成css
// 2. 用css-loader 读出内容
// 3. style-loader把读出的内容以style标签的格式
// 附加在.html文件上
use: ['style-loader','css-loader', 'less-loader'] // 设置要处理的loader
}
]
}
}
注意:如上配置中,对于less文件的处理涉及三个loader,其处理顺序是less-loader --> css-loader–>style-loader。
- less-loader:用来加载less文件,并处理成css
- css-loader:用来加载css文件
- style-loader:用来将css代码以style标签的格式插入到html文件中
自动添加css样式前缀
目标:通过postcss及相关工具来处理兼容性问题—自动添加样式前缀
步骤
-
安装依赖
-
补充loader
-
单独设置postcss
安装依赖
npm i postcss postcss-loader autoprefixer -D
补充loader
{
test: /\.less$/,
// 匹配成功后(从后向前;从右到左)
// 1. 先用less-loader去加载.less文件,转成css
// 2. 用postcss-loader配合autoprofixer加浏览器前缀
// 3. 先用css-loader去加载css文件
// 4. 再用style-loader把样式以style标签的方式嵌入到html中
use:['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
}
单独设置 postcss.config.js
const autoprefixer = require('autoprefixer')
module.exports = {
plugins:[
autoprefixer({
// last 2 versions : 浏览器最近的2版本
// >1% 全球市场占有率在1%以上的浏览器
// overrideBrowserslist: ['last 2 versions', '> 1%']
})
]
}
默认是兼容所有最新版本
例子 | 说明 |
---|---|
> 1% | 全球超过1%人使用的浏览器 |
> 5% in US | 指定国家使用率覆盖 |
last 2 versions | 所有浏览器兼容到最后两个版本根据CanIUse.com追踪的版本 |
Firefox ESR | 火狐最新版本 |
Firefox > 20 | 指定浏览器的版本范围 |
not ie <=8 | 方向排除部分版本 |
Firefox 12.1 | 指定浏览器的兼容到指定版本 |
unreleased versions | 所有浏览器的beta测试版本 |
unreleased Chrome versions | 指定浏览器的测试版本 |
since 2013 | 2013年之后发布的所有版本 |
特别地:对于要支持的浏览器的设置,也可以写在package.json中
{
// ......
"browserslist": "ie 10"
}
如果只支持ie 10 ,则flex只会加-ms-前缀
查看当前支持的浏览器的列表npx browserslist
file-loader-处理字体文件
目标:在项目中支持字体文件
步骤:
在src中添加字体文件及对应的css
-src
----/css
--------iconfont.css
----/fonts
--------iconfont.woff
在index.html中引用
<div id="app"></div>
<span class="icon-book iconfont"></span>
安装loader
npm i file-loader -D
配置文件
{
test:/\.woff$/,
use:{
loader: 'file-loader',
options: {
// [name]: 这里[]表示里面放一个占位符。name就是要处理的文件名
// [ext]: 这里[]表示里面放一个占位符。ext就是要处理的文件后缀名
name: '[name].[ext]',
outputPath: './fonts'
}
}
}
file-loader的作用就是拷贝
url-loader处理图片
参考链接:npm官网
目标:在项目中支持对图片的处理:如果足够小就直接生成对应的base64编码值,否则就直接拷贝到制定位置。
修改代码
提前准备图片
- 在src下新增目录:img,并在其下放置两张图片:一张图片大一些,一张图片小一些(可以自己找图片)。
- webpack.png: 49.4kb
- webpack.svg: 3kb
在css中引入图片
- 在style.css中引入图片,作为div标签的background。
@import "public.css";
div {
border:4px solid #ccc;
width: 50%;
height: 200px;
margin:30px auto;
box-shadow: 3px 3px 3px #ccc;
background-color:pink;
text-align: center;
+ background-image: url('../img/webpack.png')
}
body {
+ background-image: url('../img/webpack.svg')
}
直接打包,会报错。报错的原因是.svg, .png格式的文件webpack并不能直接处理。
把上面的配置文件中的file-loader直接改成url-loader,就会实现拷贝的功能。
增强版的file-loader —> url-loader
npm i url-loader -D
{
test: /\.(png|svg|jpg)$/, // jpg
use: {
loader: 'url-loader',
// url-loader是增强版的file-loader
// 如果图片小于指定的大小,则会转成base64,否则就调用file-loader进行拷贝
options: {
limit: 3*1024, // 如果图片小于3k就转成base64,否则就直接拷贝
name: '[name].[ext]',
outputPath: './img'
}
}
}
使用babel-loader处理js降级问题
能够把es6高级内容变为es5的loader名称为 babel-loader
es6/es7/es8等等高级标准有很多(let、箭头函数、对象解构赋值、…展开运算符、字符串模板等等),每个标准都需要一个独立的plugin进行降级处理,如果使用许多高级标准内容,那么势必要为此安装许多plugin,这样工作比较繁琐,系统已经考虑到这点了,其通过preset把许多常用的plugin给做了集合,因此一般性的使用只需要安装preset即可搞定(如果项目应用到了一个生僻的高级标准内容,preset处理不来,就还需要再安装对应的plugin处理)
npm官网: babel-loader
babel官网:https://www.babeljs.cn/setup#installation
步骤:
-
安装依赖包
npm i babel-loader @babel/core @babel/preset-env -D
-
在webpack.config.js中做如下配置:
{ test: /\.js$/, exclude: /node_modules/, // 排除目录 use: [ { loader:'babel-loader', options: { presets: ['@babel/preset-env'] } } ] // es6转es5 }
说明: @babel/preset-env用来指定按什么样的预设来进行降级处理
-
打包测试
打包之后,去打包后的文件中检查是否已经把const和箭头函数这种es6的代码转成了es5的代码。
小结
- 一切皆模块,非js模块有对应的loader来处理
- loader使用的基本步骤
- 第一步:安装包
cn/setup#installation
- 第一步:安装包
步骤:
-
安装依赖包
npm i babel-loader @babel/core @babel/preset-env -D
-
在webpack.config.js中做如下配置:
{ test: /\.js$/, exclude: /node_modules/, // 排除目录 use: [ { loader:'babel-loader', options: { presets: ['@babel/preset-env'] } } ] // es6转es5 }
说明: @babel/preset-env用来指定按什么样的预设来进行降级处理
-
打包测试
打包之后,去打包后的文件中检查是否已经把const和箭头函数这种es6的代码转成了es5的代码。
小结
- 一切皆模块,非js模块有对应的loader来处理
- loader使用的基本步骤
- 第一步:安装包
- 第二步:配置rules