webpack 最出色的功能之一就是,除了 JavaScript,还可以通过 loader 引入任何其他类型的文件。
我们先介绍下loader```````
Loader
webpack 只能理解 JavaScript 和 JSON 文件
,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理图片、CSS、TS文件等其他类型的文件
,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中
。
loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript,或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS文件!loader 对模块的源代码进行转换,并在bundle中引入这些依赖。
本质上,webpack loader 将所有类型的文件,转换为应用程序的依赖图(和最终的 bundle)可以直接引用的模块。
注意:
loader 能够 import 导入任何类型的模块(例如 .css 文件)
,这是 webpack 特有的功能,其他打包程序或任务执行器的可能并不支持。
举几个使用Loader的例子:
- 它可以把SASS文件的写法转换成CSS,而不在使用其他转换工具。
- 它可以把ES6或者ES7的代码,转换成大多浏览器兼容的JS代码。
- 它可以把React中的JSX转换成JavaScript代码。
注意:
所有的Loader都需要在npm中单独进行安装,并在webpack.config.js里进行配置。
下面我们对Loader的配置型简单梳理一下。
- test:用于匹配处理文件的扩展名的表达式,这个选项是必须进行配置的;
- use:loader名称,就是你要使用模块的名称,这个选项也必须进行配置,否则报错;
- include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹);(可选)
- query:为loaders提供额外的设置选项。(可选)
明白了Loader后,现在开始进入正题。
一、加载CSS
1、安装
为了从 JavaScript 模块中 import 一个 CSS 文件,我们需要在 module 配置中 安装并添加 style-loader
和 css-loader
,在终端输入:
> sudo npm install --save-dev style-loader css-loader
2、添加规则
接着我们修改上篇文章的webpack.config.js文件,为module添加规则,
webpack.config.js
const path = require('path');
module.exports={
entry:{
entry:'./src/entry.js'
},
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'dist'),
},
module:{
rules:[
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
}
]
},
plugins:[],
devServer:{}
}
webpack 是根据正则表达式来确定应该查找哪些文件的,并将其提供给指定的 loader。上面添加代码的意思:
以 .css 结尾的全部文件都将被提供给 style-loader 和 css-loader
。
3、创建css并引入
现在我们在./src中创建style文件夹(用于存放css样式)
然后再在./src/style中创建index.css文件,
src/index.css
#title{
width:100px;
height:200px;
background: red;
}
然后将src中的entry.js改为:
import './style/index.css';
document.getElementById('title').innerHTML='Hello Webpack';
此时项目的目录结构:
4、执行
现在运行构建命令:
> npm run build
再次在浏览器中打开 index.html,你应该看到 Hello webpack 现在的样式是红色。要查看 webpack 做了什么,请检查页面(不要查看页面源代码,因为它不会显示结果),并查看页面的 head 标签,
如图,它包含着我们在 index.js 中导入的 style 块元素:
二、加载图片
如果现在我们正在下载 CSS,但是我们的背景和图标这些图片,要如何处理呢?使用 file-loader,我们可以轻松地将这些内容混合到 CSS 中:
1、安装
sudo npm install --save-dev file-loader
2、添加规则
接着我们修改上面的webpack.config.js文件
webpack.config.js
const path = require('path');
module.exports = {
entry:{
entry:'./src/entry.js',
},
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'dist'),
},
module:{
rules:[
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
},
{
test:/\.(png|svg|jpg|gif)$/,
use:['file-loader']
}
]
},
plugins:[],
devServer:{}
};
3、加图片 并使用
现在我们在./src中创建image文件夹(用于存放图片)
然后再在./src/image中添加图片test.png,此时 项目目录:
然后修改src中的entry.js:
import './style/index.css';
import Icon from './image/test.png';
document.getElementById('title').innerHTML='Hello Webpack';
// 将图像添加到我们现有的 div
var myIcon = new Image();
myIcon.src = Icon;
document.getElementById('title').appendChild(myIcon);
我们也可以在css中使用图片,
src/style/index.css
#title{
width:100px;
height:200px;
background: url('../image/test.png');
}
4、执行
让我们重新构建,并再次打开 index.html 文件:
再次在浏览器中打开 index.html,你应该看到变化。
如果你检查此元素,你将看到实际的文件名已更改为像1b7d5c92bee0c748e6b57bda67097f18.png 一样,dist中也能看到处理后的图片。这意味着 webpack 在 src 文件夹中找到了该图片并成功处理!
三、加载字体
那像字体这样的其他资源如何处理呢?file-loader 和 url-loader 可以接收并加载任何文件然后将其输出到构建目录。这就是说,我们可以将它们用于任何类型的文件,包括字体。让我们更新 webpack.config.js 来处理字体文件:
1、安装
前面已经安装了file-loader,所以跳过
2、添加规则
接着我们修改上面的webpack.config.js文件
webpack.config.js
const path = require('path');
module.exports = {
entry:{
entry:'./src/entry.js',
},
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'dist'),
},
module:{
rules:[
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
},
{
test:/\.(png|svg|jpg|gif)$/,
use:['file-loader']
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ['file-loader']
}
]
},
plugins:[],
devServer:{}
};
3、加字体 并使用
现在我们在./src中创建font文件夹(用于存放字体)
然后再在./src/font中添加my-font.woff、my-font.woff2,此时 项目目录结构:
通过配置好 loader 并将字体文件放在合适的地方,你可以通过一个 @font-face 声明引入。本地的 url(…) 指令会被 webpack 获取处理,就像它处理图片资源一样:
src/style/index.css
@font-face {
font-family: 'MyFont';
src:url('../font/my-font.woff2') format('woff2'),
url('../font/my-font.woff') format('woff');
font-weight: 600;
font-style: normal;
}
#title{
font-family: 'MyFont';
width:100px;
height:200px;
background: url('../image/test.png');
}
4、执行
现在运行构建命令:
> npm run build
重新打开 index.html 看看我们的 Hello webpack 文本显示是否换上了新的字体。
三、加载数据
此外,可以加载的有用资源还有数据,如 JSON 文件,CSV、TSV 和 XML。类似于 NodeJS,JSON 支持实际上是内置的,也就是说 import Data from ‘./data.json’ 默认将正常运行(即若要引入.json文件,无须进行下面的安装,直接像下面3一样使用.json文件即可)
。
1、安装
要导入 CSV、TSV 和 XML,你可以使用 csv-loader 和 xml-loader。让我们处理这三类文件:
sudo npm install --save-dev csv-loader xml-loader
2、添加规则
接着我们修改上面的webpack.config.js文件
webpack.config.js
const path = require('path');
module.exports = {
entry:{
entry:'./src/entry.js',
},
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'dist'),
},
module:{
rules:[
{
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
},
{
test:/\.(png|svg|jpg|gif)$/,
use:['file-loader']
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ['file-loader']
},
{
test: /\.(csv|tsv)$/,
use: ['csv-loader']
},
{
test: /\.xml$/,
use: ['xml-loader']
}
]
},
plugins:[],
devServer:{}
};
3、加数据并使用
现在我们在./src中创建data.xml,
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Mary</to>
<from>John</from>
<heading>Reminder</heading>
<body>Call Cindy on Tuesday</body>
</note>
此时 项目目录结构:
现在我们可以 import 这四种类型的数据(JSON, CSV, TSV, XML)中的任何一种,所导入的 Data 变量将包含可直接使用的已解析 JSON:
src/index.js
import './style/index.css';
import Icon from './image/test.png';
import Data from './data.xml';
document.getElementById('title').innerHTML='Hello Webpack';
var myIcon = new Image();
myIcon.src = Icon;
document.getElementById('title').appendChild(myIcon);
console.log(Data);
在使用 d3 等工具来实现某些数据可视化时,预加载数据会非常有用。我们可以不用再发送 ajax 请求,然后于运行时解析数据,而是在构建过程中将其提前载入并打包到模块中,以便浏览器加载模块后,可以立即从模块中解析数据。
4、执行
让我们重新构建:
> npm run build
打开 index.html 并查看控制台:
四、全局资源
上述所有内容中最出色之处是,以这种方式加载资源,你可以以更直观的方式将模块和资源组合在一起。无需依赖于含有全部资源的 /assets 目录,而是将资源与代码组合在一起。例如,类似这样的结构会非常有用:
这种配置方式会使你的代码更具备可移植性,因为现有的统一放置的方式会造成所有资源紧密耦合在一起。假如你想在另一个项目中使用 /my-component,只需将其复制或移动到 /components 目录下。只要你已经安装了任何扩展依赖(external dependencies),并且你已经在配置中定义过相同的 loader,那么项目应该能够良好运行。
但是,假如你无法使用新的开发方式,只能被固定于旧有开发方式,或者你有一些在多个组件(视图、模板、模块等)之间共享的资源。你仍然可以将这些资源存储在公共目录(base directory)中,甚至配合使用 alias 来使它们更方便 import 导入。