tree-shaking主要实现的是按需加载
1.babel-plugin-import使用
babel中已经有了实现按需加载的包,
babel-plugin-import,我们接下来看一下,在使用和不实用这个插件tree-shaking影响有多大
1.1.依赖
npm i webpack webpack-cli babel-plugin-import babel-loader @babel/core babel -D
npm i lodash -S
1.2.使用
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader'
}
}
]
}
}
src/index.js
import {flatten,concat} from 'lodash'
console.log(concat)
console.log(flatten)
打包编译需要的是485KiB
- 使用babel-plugin-import
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
plugins: [['import', {
libraryName: "lodash",
libraryDirectory: "",
camel2DashComponentName: false, // default: true
}]]
}
}
}
]
}
}
打包编译21.8KiB,相比485KiB小了不少,我们可以直观的看出
tree-shaking在项目中的重要性,他决定着你的项目在上显示的大小
实现babel-import-plugin插件
- 如果代码中在使用lodash时如下这种方式的引用也能达到目的
import flatten from 'lodash/flatten';
import concat from 'lodash/concat';
console.log(concat)
console.log(flatten)
-
但是我们往往在开发中很少这么去写,太过于麻烦,我们希望保持原来的引用,达到上面的效果,所以对于我们插件来说,就是实现一个将
import {concat} from 'lodash'转换成import concat from 'lodash/concat'的过程; -
import {concat} from 'lodash'语法树
import concat from 'lodash/concat'语法树
const t = require('babel-types');
const visitor = {
ImportDeclaration(path, state = { opts: {} }) {
const { node } = path;
const { opts } = state;
const specifiers = node.specifiers;
const source = node.source;
if (opts.libraryName === source.value && !t.isImportDefaultSpecifier(specifiers[0])) {
const defaultImportDeclaration= specifiers.map((specifier) => {
const defaultSpecifier = t.importDefaultSpecifier(specifier.local)
const importDeclaration = t.importDeclaration([defaultSpecifier], t.stringLiteral(`${source.value}/${specifier.local.name}`))
return importDeclaration;
})
path.replaceWithMultiple(defaultImportDeclaration);
}
}
}
module.exports = function (babel) {
return {
visitor
}
}