目标:
能处理css,less文件,解决css的浏览器兼容性配置能处理字体文件能处理图片文件能处理js降级问题在webpack看来 一切皆模块,图片,样式文件,js文件… 。 但是webpack默认只能处理js模块,对于非js的内容它就需要一些帮手来处理了。这些帮手就是loader。
webpack 可以使用 loader 来预处理文件。这允许你打包除 JavaScript 之外的任何静态资源。
下面,我们来讨论如何处理.css文件。
在src目录下,再次创建一个css目录
|-src |-src/css |--------public.css |--------style.csssrc/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会怎么样呢?
下面,我们修改自已的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来处理。
对于所有的loader的使用,其基本步骤是一致的,分成两步:
安装loader包 配置webpack.config.js中的module它也是开发依赖。
修改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代码。
如果我们希望样式生效,最终在.html文件中有两种情况:
有style标签有link标签而css-loader只是能让你在.js中通过import来引入.css,如果你希望引入的css代码最终以style标签的方式插入到html页面中,则还需要安装一个loader:style-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这个方法,你就可以发现这个过程。
在webpack看来,一切皆模块: 每一个文件都是一个模块。
webpack默认只能处理json和js模块,对于其它的模块它需要对应的loader来处理
loader的基本使用是:
安装Loader (npm 包)配置module中的rules:用loader来处理对应类型的文件目标:在项目中支持使用less来写css代码。
在src目录的css目录下创建 index.less,则内容如下:
@import "style.css"; body{ div { padding:50px; } }在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')参考官网
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–>cssless-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文件,并处理成csscss-loader:用来加载css文件style-loader:用来将css代码以style标签的格式插入到html文件中目标:通过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 20132013年之后发布的所有版本特别地:对于要支持的浏览器的设置,也可以写在package.json中
{ // ...... "browserslist": "ie 10" }如果只支持ie 10 ,则flex只会加-ms-前缀
查看当前支持的浏览器的列表npx browserslist
目标:在项目中支持字体文件
步骤:
在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的作用就是拷贝
参考链接:npm官网
目标:在项目中支持对图片的处理:如果足够小就直接生成对应的base64编码值,否则就直接拷贝到制定位置。
直接打包,会报错。报错的原因是.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' } } }能够把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的代码。
步骤:
安装依赖包
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的代码。
