Abstract syntax tree Abstract syntax tree Abstract syntax tree Abstract syntax tree

Background: When we introduce two methods in a package at the same time, there are two forms

The first form

import {flatten,join} from 'lodash';
Copy the code

Second form

import flatten from 'lodash/flatten';
import join from 'lodash/join';
Copy the code

Comparing the two forms, we can see:

The introduction of the first method introduces the entire Lodash package and the second method guides two methods into the entire package

Obviously we’re going to use the second one

However, most projects are in the form of import deconstruction, so we will write a plug-in here, and when we write the first form, we will use the plug-in to convert it into the second form

This is the function of the plug-in we are going to write

Step 1: Initialize a Webpack project

 npm i webpack webpack-cli babel-core babel-loader babel-preset-env babel-preset-stage-0 -D
Copy the code

In Webpack, the mode variable is provided to configure the runtime environment, and the value of mode can be development, which stands for development mode, or production, which stands for production mode.

Write the compiled command in package.json

"scripts": {"build":"webpack --mode production/development"
}
Copy the code

Step 2: Create a project structure

Webpack-plugin // project name dist // Bundle output directory bundle.js // package output file SRC // main logic index.js // project entry file./ /babelrc // syntax parsing configuration package.json webpack.config.jsCopy the code

Step 3: Write the webPack configuration file

const path = require('path');
module.exports = {
    entry: './src/index.js'// output: {path: path.join(__dirname,'dist'), // output path filename:'bundle.js'// configure module: {// configure loader rules: [{test: /\.js$/,
                loader: 'babel-loader'}}}]Copy the code

Step 4: Configure.babelrc

{
  "presets": [
    "env"."stage-0"]."plugins": [[/ /"demand-loading"// This is a plugin name that we wrote ourselves."library": "lodash"// Which library do we use when we reference lodash library},"syntax-decorators"]]}Copy the code

Step 5: Write the comparison script in index.js

 // import {flatten,join} from 'lodash'
import flatten from 'lodash/flatten'
import join from 'lodash/join'
Copy the code

Let’s introduce the last two sentences and wrap them up

Hash: fCB0bd5D9734b5f56676 Version: webPack 4.2.0 Time: 346ms Built at: [emitted by means of Entrypoint main = bundle.js] Asset Size Chunks bundle.js [./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 823 bytes {main} [built] [./src/index.js] 286 bytes {main} [built] + 15 hidden modulesCopy the code

Looking at the packaged code in this way, we see that this way into the packaged size is. 21.3 k.

Then comment out the next two lines and introduce only the first line

    Hash: aa8b689e1072463fc1cd
Version: webpack 4.2.0
Time: 3277ms
Built at: 2018-3-27 21:30:22
    Asset     Size  Chunks             Chunk Names
bundle.js  483 KiB    main  [emitted]  main
Entrypoint main = bundle.js
[./node_modules/webpack/buildin/amd-options.js] (webpack)/buildin/amd-options.js 82 bytes {main} [built]
[./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 823 bytes {main} [built]
[./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 521 bytes {main} [built]
[./src/index.js] 47 bytes {main} [built]
    + 1 hidden module

Copy the code

The size of the package is 483K

The comparison proves the difference between the two methods of introduction

Step 6: Let’s write the plugin!

Let’s start by comparing the abstract syntax trees of the two introductions

By comparison, we find that the ImportDeclaration is different


	const babel = require('babel-core');
	const types = require('babel-types');
	
	letVisitor = {// Where ref is the second parameter to ImportDeclaration, where the value is {// in.babelrc"library": "lodash"ImportDeclaration(path, ref={options:{}}) {ImportDeclaration(path, ref={options:{}}) {let node = path.node;
	        let specifiers = node.secifiers
	        if(options.library == node.soure.value && ! types.isImportDeclaration(specifiers[0])) {let newImport = specifiers.map((specifier) => (
	                types.importDeclaration([types.ImportDefaultSpecifier(specifier.local)], types.stringLiteral(`${node.soure.value}/${specifier.local.name}`)))); path.replaceWithMultiple(newImport) } } } const code ="import {flatten, join} from 'lodash';";
	
	let r = babel.transform(code, {
	    plugins: [
	        {visitor}
	    ]
	})

Copy the code

When creating the replacement logic, the methods on Types use this url on Github, which doesn’t search for which, mom doesn’t have to worry about my learning anymore. Hee hee

Step 7: Tidy up the above code and put it in node_modules

Create a new folder named “babel-plugin-demand-loading” and place it in node_modules. Create a new file named “index.js” and put the following code init. Then go to this folder and initialize a package.json file. The entry file inside is called index.js

Matters needing attention:

The Babel plugin must be named babel-plugin-xxx(the name of the plugin you wrote), otherwise it will not be successful. The Babel plugin returns an object with a visitor object that holds our conversion code


	const babel = require('babel-core');
	const types = require('babel-types'); Module.exports = {visitor: {// where ref is the second parameter of ImportDeclaration, where the value is {// in. Babelrc"library": "lodash"ImportDeclaration(path, ref={}) {ImportDeclaration(path, ref={}) {let { opts } = ref
	            let node = path.node;
	            let specifiers = node.specifiers
	            if(opts.library == node.source.value && ! types.isImportDeclaration(specifiers[0])) {let newImport = specifiers.map((specifier) => (
	                    types.importDeclaration([types.ImportDefaultSpecifier(specifier.local)], types.stringLiteral(`${node.source.value}/${specifier.local.name}`)))); path.replaceWithMultiple(newImport) } } } }Copy the code

Finally, after NPM run build is compiled, it is found that the packaged size is. 20k plus means our plugin works.

Do you know how to do it by now? Hee hee!

Don’t be bored with the familiar, make a little progress every day; Don’t be afraid of new things. Learn a little every day.