loader
概念
loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。
https://www.webpackjs.com/loaders/
https://www.webpackjs.com/loaders/file-loader/
npm install file-loader -D
| var Header = require('./header.js');
var Sidebar = require('./sidebar.js');
var Content = require('./content.js')
var Content = require('./content.js')
var avatar = require('./avatar.jpg')
console.log(avatar)
new Header();
new Sidebar();
new Content();
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
module: {
rules: [{
test: /\.jpg$/,
use: {
loader: 'file-loader'
}
}]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
|
console.log
打印出的内容为:30267bc9fc1c4107fffd6d34188a893f.jpg
即打包生成的文件名
| import avatar from './avatar.jpg'
var img = new Image();
img.src = avatar;
var root = document.getElementById('root');
root.append(img);
|
如果要使用.vue
文件,那么就需要相关的loader
https://vue-loader.vuejs.org/zh/
打包静态资源(图片)
打包后指定图片文件名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
module: {
rules: [{
test: /\.(jpg|pnd|gif)$/,
// test: /\.jpg$/,
use: {
loader: 'file-loader',
options: {
// 加中括号的名称为 placeholder 占位符
name: '[name].[ext]'
// name: '[name]_[hash].[ext]'
}
}
}]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
|
指定outputPath
| options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/'
}
|
使用url-loader
https://www.webpackjs.com/loaders/url-loader/
直接将file-loader
改成url-loader
即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
module: {
rules: [{
test: /\.(jpg|pnd|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/'
}
}
}]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
|
如果图片非常小,比较适合将其放到js
文件中打包,否则以图片形式打包更好,可以对此进行配置
| use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 20480
}
}
|
当图片大小小于limit
的值,则会打包到js
中,否则以图片形式打包
打包静态资源(样式一)
| npm install style-loader css-loader -D
|
index.css
| .avatar {
width: 150px;
height: 150px;
}
|
index.js
| import avatar from './avatar.jpg';
import './index.css';
var img = new Image();
img.src = avatar;
img.classList.add('avatar')
var root = document.getElementById('root');
root.append(img);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
module: {
rules: [{
test: /\.(jpg|pnd|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 20480
}
}
},{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
|
avatar.css
| .avatar {
width: 150px;
height: 150px;
}
|
index.css
css-loader 解释(interpret) @import 和 url() ,会 import/require() 后再解析(resolve)它们。
sass-loader
https://www.webpackjs.com/loaders/sass-loader/
npm install sass-loader node-sass --save-dev
index.scss
| body {
.avatar {
width: 150px;
height: 150px;
}
}
|
index.js
| import avatar from './avatar.jpg';
import './index.scss';
var img = new Image();
img.src = avatar;
img.classList.add('avatar')
var root = document.getElementById('root');
root.append(img);
|
loader 的执行顺序为:从下到上,从右到左
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | module: {
rules: [{
test: /\.(jpg|pnd|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 20480
}
}
},{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}]
},
|
使用postcss-loader
https://www.webpackjs.com/loaders/postcss-loader/
npm install autoprefixer -D
postcss.config.js
| module.exports = {
plugins: [
require('autoprefixer')
]
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | module: {
rules: [{
test: /\.(jpg|pnd|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 20480
}
}
},{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
'postcss-loader'
]
}]
},
|
index.scss
| body {
.avatar {
width: 150px;
height: 150px;
transform: translate(100px, 100px);
}
}
|
打包静态资源(样式二)
avatar.scss
| body {
.abs {
background: red;
}
}
|
index.scss
| @import './avatar.scss';
body {
.avatar {
width: 150px;
height: 150px;
transform: translate(100px, 100px);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | module: {
rules: [{
test: /\.(jpg|pnd|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 20480
}
}
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2 // 保证依次从下往上调用loader(先执行下面两个loader)
}
},
'sass-loader',
'postcss-loader'
]
}]
},
|
样式冲突:
index.js
| import avatar from './avatar.jpg';
import './index.scss';
import createAvatar from './createAvatar.js';
createAvatar()
var img = new Image();
img.src = avatar;
img.classList.add('avatar')
var root = document.getElementById('root');
root.append(img);
|
createAvatar.js
| import avatar from './avatar.jpg';
function createAvatar() {
var img = new Image();
img.src = avatar;
img.classList.add('avatar')
var root = document.getElementById('root');
root.append(img);
}
export default createAvatar;
|
打包后会出现两张图片,样式都会作用在这两张图片上
为了让css只在某个文件有效,修改webpack.config.js
添加modules: true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | module: {
rules: [{
test: /\.(jpg|pnd|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 20480
}
}
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true
}
},
'sass-loader',
'postcss-loader'
]
}]
},
|
就可以写下面的语法import style from './index.scss';
index.js
| import avatar from './avatar.jpg';
import style from './index.scss';
import createAvatar from './createAvatar.js';
createAvatar()
var img = new Image();
img.src = avatar;
img.classList.add(style.avatar)
var root = document.getElementById('root');
root.append(img);
|
createAvatar.js
1
2
3
4
5
6
7
8
9
10
11
12 | import avatar from './avatar.jpg';
import style from './index.scss';
function createAvatar() {
var img = new Image();
img.src = avatar;
img.classList.add(style.avatar)
var root = document.getElementById('root');
root.append(img);
}
export default createAvatar;
|
字体打包
https://www.iconfont.cn/
| ➜ font pwd
lesson/src/font
➜ font ls
iconfont.eot iconfont.svg iconfont.ttf iconfont.woff
|
index.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 | @font-face {font-family: "iconfont";
src: url('./font/iconfont.eot?t=1570329100796'); /* IE9 */
src: url('./font/iconfont.eot?t=1570329100796#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAOwAAsAAAAAB7wAAANkAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDDAqDDIJiATYCJAMQCwoABCAFhG0HQxu/BlGUDkaP7IckyZkKhRDDsi9AYJkqzQAFCgAsAFCACKL9frN391UgSRKNdLEsWj2RCZ0EoZEiJROKl/Aup/pZg5f+cW9o1LXQRFORX4rieW9lsU5AQ2hpCWgBbAEr7KCcJh2NtAP5Q9QtXLs4nDbPA5tvWS5zjPMxARMMbOwBFmCJZN5jbKDdz3oCbQscjYPD8yvoK4xugXgyWkA/pVRqMkNTqJeMLeINgWZ6SV/Aq//9+BdFn6SWGX2PHw8S2P5S+9LIT1UcFxeBNZ4e3CQyNoFCXJcaT7XC4KaWthJsWwbrahZ8aVQVX2ouc7VNCEkm4K+z0rtgCwX5lFg2heBLXSGdIQuTZEAXTXcSfgbeETt315CkcTze6skNo9rEd2YykF5YmtkeR+/TFLl8zIMpXrGzO7UnhWSQ1LxvURFACjqgDXp90icn+k1j9EfHtpmn9sfHDKDuSJ9y5YSXoPEUOa4e4+aSiScnWq2jwadVD7ElK25ncI1ro6fM6GB1L+1kIiOrOVAc2vvLG0i1sd3iLefdVDLea5M3nXfK1pYLSH9QWiBEUENdY80WISZqzORcrTzHPedmlmcMrRa4FxTruVXY6k1YCtiNf8dnFHHY4hB8lICV17EVOXB8JiBAyIKzs4Az3EO31yeYd2bUX9PCFV+Wrsi3wZWEyM3dEJo090yIPF+tqQRuqZVenWkMgIAblfVr0Q3X7d3dC6jAaIiXjFEH8P+W8/GofNxYtvlFAAACmer61+5U6u7/m6MCPmdrcnBUnwXap2hKcKxfw2pZVlSOoSpF5tpMzVwc9e6a0NZGBYZ17HcM8UzrdELTTAxJwzxkTYvIgt2Emo4tqGvahrYNR5M7JlhLlBbWvQOEoQ9I+j4gG/pGFuwP1Mz6g7phtKDtMiZzdiyHGe4zCUsJTtZoZFkoS2OHQeYF6XkmOMnx8TfEtfFg6AXZyBEVxGMMqBc6slah4jLHQ9iMsqzEissZSetNra1i31dlL/JkmcPQPkYEiyTQxBoypFJBubWtYe7zF4g2lxG4JqtCfYOwmqkfhTxBC+SRsGiVdS2X1Ba0iGUpSGGlHDoEPcnMYAlV5a1miGR5pj38lZhPqqm2Qm9+cf4AGVwexhwlUuQoUdO+YS6XbmIPKbo3manEunUrNAA=') format('woff2'),
url('./font/iconfont.woff?t=1570329100796') format('woff'),
url('./font/iconfont.ttf?t=1570329100796') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('./font/iconfont.svg?t=1570329100796#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.iconarrow-down:before {
content: "\e63b";
}
.iconalipay:before {
content: "\e63c";
}
.iconbag:before {
content: "\e63d";
}
|
index.js
| var root = document.getElementById('root');
import './index.scss'
root.innerHTML = '<div class="iconfont iconalipay"></div>'
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 | module: {
rules: [{
test: /\.(jpg|pnd|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 20480
}
}
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader'
}
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
}]
},
|