webpack loaders和plugins介绍
什么是loaders
对于webpack来说,默认只能打包处理JS文件,或者说是JS模块,但是作为一个模块打包工具,需要打包的模块肯定不仅仅只有JS模块,还有图片,CSS模块等。
但webpack不能打包除JS模块之外的其他模块。
所以需要引入第三方loader告诉它,碰见这些文件要怎么办。
所以,loader就是一个打包方案,仅仅是为了打包。
什么是plugins
loaders用来转换某种特定类型的模块,plugins则是用来在一些合适的时机执行一些特定的任务,比如代码分割、打包优化、压缩等。
扩展webpack的功能的,目的是做任何loaders做不了的事情。
是作用于webpack本身上,可以在webpack运行到某个时刻的时候,做一些事情,在整个编译周期都起作用。
loaders和plugins的区别
- loader在模块加载时的预处理文件,运行在打包文件之前。
- plugins处理loader无法处理的事物,在整个编译周期都起作用。
常用的loaders介绍
file-loader
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'file-loader',
options: {},
},
}
- 实现方式:依靠webpack提供的强大的API,自己本身并没有做多少工作,完全不用担心读写文件的问题,因为这些webpack已经封装好了
- 在js代码里import/require 一个文件时,会将该文件生成到输出目录,随机生成一个hash值,返回到require函数
let img = require('@/assets/img/default-avatar.png');
console.log(img); // 95dbac1b85f0161c12c34cbbf34d5156.png
url-loader
{
test: /\.(png|svg|jpe?g|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'img',
limit: 10240
}
}
},
- 实现方式:获取 limit 参数,如果文件大小在 limit之内,则返回文件的 base64 编码后内容;如果超过了 limit ,则调用file-loader,调用的时候,会将options内容也传递给file-loader
- url-loader 默认 limit 是没有限制,如果没有设置,不管多大的图片都会转换为 base64 编码字符串。
url-loaders2.png
module.exports = {
module: {
rules: [
{
test: /\.less$/,
use: [
{
loader: 'style-loader', // creates style nodes from JS strings
},
{
loader: 'css-loader', // translates CSS into CommonJS
},
{
loader: 'less-loader', // compiles Less to CSS
},
],
},
],
},
};
less-loader
- 将less编译成 css
- 交给css-loader
css-loader
- 主要用来解析css中的静态资源,将@import和url()解析为import/require(),解析出的除css以外的静态资源,一般交给url-loader和file-loader去处理
- 为了不造成冲突,css-loader可以按照一定的规则将类名等转化成具有全局唯一性的名字
- 将css转化为commonjs
postcss-loader
- 配合postcss.config.js使用
- css3新特性加厂商前缀(autoprefixer)
- 如果在浏览器中没有看到加前缀,是因为浏览器版本较高
- 可以对css进行各种处理,功能强大,比如自动添加css前缀,也可自定义插件
style-loader
- 将样式挂在在head里
- 通过注入<style>标签将CSS添加到DOM
loader的使用
- loader的执行顺序是从下到上,从右到左
- 他们的解析过程是链式的,所以在use数组中下面的部分会先执行,所以他们的执行顺序其实是less-loader > css-loader > style-loader
- 前一个loader的结果是下一个loader的输入,最后一个loader的输出就是我们要的结果。
{
test: /\.less/,
use: [
'style-loader',
{
loader: 'css-loader'
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: loader => [
require('autoprefixer')({
browsers: ['last 2 versions', 'ios >= 8']
})
]
}
},
{
loader: 'less-loader'
}
]
// use style-loader in development
},
编写一个超简单的loader
loader文件
module.exports = function (source) {
return source.replace('winnie', 'world')
}
loader使用
resolveLoader: {
modules: ['node_modules', './loaders']
},
module: {
rules: [{
test: /\.js/,
use: [{
loader: 'replaceLoader',
},
]
}]
},
常用的plugins介绍
html-webpack-plugin
- 会在打包结束后,自动生成一个html文件,并把打包生成的js文件自动引入到这个html中,打包之后运行
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new HtmlWebpackPlugin({ // 生成一个html文件,并且将打包文件插入到html中
filename: 'index.html',
template: 'index.html',
title: '小白营',
}),
]
clean-webpack-plugin
- 打包之前运行,默认移除webpack的output中的所有文件,然后将输出的文件输出到输出目录中
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
plugins: [
new CleanWebpackPlugin(), // 打包前清空打包文件
]
DllPlugin
- 用于打包出一个个单独的动态链接库文件
DllReferencePlugin 插件
- 用于在主配置文件中去引入 DllPlugin 插件打包好的动态链接库文件
- DllPlugin和DllReferencePlugin需要配合使用
webpack性能优化
-
使用DllPlugin提高打包速度:目的-引入的第三方模块只打包一次保存,之后打包不再重复编译
-
配置webpack.dll.js文件:将第三方模块单独打包,用library将第三方模块的代码通过全局变量的方式暴露出去,然后借助DLLPlugin插件分析暴露出去的代码,生成manifest.json映射文件
-
manifest.json用于描述动态链接库文件中包含哪些模块
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode:'production',
entry: {
vendors:['lodash','react','react-dom',]
},
output: {
path: path.resolve(__dirname, '../dll'),
filename:'[name].dll.js',
library:'[name]'
},
plugins:[
new webpack.DllPlugin({
name: '[name]',
path: path.resolve(__dirname, '../dll/[name].manifest.json')
})
]
}
- 引入AddAssetHtmlWebpackPlugin,将打包的dll文件引入html
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
new AddAssetHtmlWebpackPlugin({
filepath: path.resolve(__dirname,'../dll/vendors.dll.js')
}),
- 引入DllReferencePlugin,结合生成的dll文件和引入的第三方模块,分析manifest.json,打包时,三方代码直接从生成的dll文件中拿
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname,'../dll/vendors.manifest.json')
})
- manifest.json清楚地描述了与其对应的 dll.js 文件中包含了哪些模块,以及每个模块的路径和 ID
manifest.png
- 一个动态链接库文件中包含了大量模块的代码,这些模块存放在一个数组里,用数组的索引号作为 ID。 并且还通过 vendors 变量把自己暴露在了全局中,也就是可以通过 window.vendors 可以访问到它里面包含的模块
vendors.png