npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

less-import-babel-plugin

v1.0.1

Published

痛点: 当我们导入lodash中指定的工具函数时 会将整个lodash打包进来

Downloads

8

Readme

less-import

痛点: 当我们导入lodash中指定的工具函数时 会将整个lodash打包进来

import {flattenDeep, chunk} from 'lodash'

换成按需引入的写法 但是这样写有些麻烦 我们想由上面写法 自动分解为下面写法 所以我们就编写一个babel插件 less-import

该 babel 插件会将import {flattenDeep, chunk} from 'lodash' 转化为下面这种写法:

import flattenDeep from 'lodash/flattenDeep'
import chunk from 'lodash/chunk'

使用

npm install less-import-babel-plugin --save

配置.babelrc

{
    "presets": [
        "env",
        "stage-0"
    ],
    "plugins": [
        [
            "less-import-babel-plugin", // 配置插件
            {
                "library": "lodash" // 指定处理的库
            }
        ]
    ]
}

原理解析

@babel/parser

babelParser 把js解析为 ast tree,然后我们对 tree 进行修改

const script = babelParser.parse(sfc.script.content, {
  sourceType: 'module',
});

可以在线 ast 转换 javascript 的网站 https://astexplorer.net/

@babel/trasform

当我们需要对 ast 改造的时候的,肯定会涉及到遍历。

主角是@babel/traverse,@babel/types和@babel/template是辅助工具

traverse 支持两个参数,第一个是 ast 树,第二个是 visitor

visitor

  • visitor 是用于 AST 遍历的跨语言的模式。
  • 就是一个对象,会在遇到合适类型节点时被执行

具体的语法:

const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default

const code = `function mirror(something) {
  return something
}`
const ast = parser.parse(code, {
  sourceType: 'module',
})
const visitor = {
  Identifier (path) {
    console.log(path.node.name)
  }
}
traverse(ast, visitor)

path

  • path是对当前访问的node的一层包装

  • 使用path.node可以访问到当前的节点,使用path.parent可以访问到父节点,这里列出了path所包含的内容

  • path中还提供了一系列的工具函数,例如traverse(在当前path下执行递归), remove(删除当前节点), replaceWith(替换当前节点)等等。

@babel/types

  • 包含了判断,新建以及变换 AST 节点的方法

比如说判断 isIdentifier

const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const t = require('@babel/types')

const code = `function mirror(something) {
  return something
}`
const ast = parser.parse(code, {
  sourceType: 'module',
})
const visitor = {
  enter(path) {
    if (t.isIdentifier(path.node)) {
      console.log('Identifier!')
    }
  }
}
traverse(ast, visitor)

比如说,生成:

const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const generate = require('@babel/generator').default
const t = require('@babel/types')

const code = `function mirror(something) {
  return something
}`
const ast = parser.parse(code, {
  sourceType: 'module',
})
const strNode = t.stringLiteral('mirror')
const visitor = {
  ReturnStatement (path) {
    path.traverse({
      Identifier(cpath){
        cpath.replaceWith(strNode)
      }
    })
  }
}
traverse(ast, visitor)
const transformedCode = generate(ast).code
console.log(transformedCode)

使用@babel/type创建一些简单节点会很容易,但是如果是大段代码的话就会变得困难了,这个时候我们可以使用@babel/template。

const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
const generate = require('@babel/generator').default
const template = require('@babel/template').default
const t = require('@babel/types')

const code = `function mirror(something) {
  return something
}`
const ast = parser.parse(code, {
  sourceType: 'module',
})
const visitor = {
  FunctionDeclaration(path) {
    // 在这里声明了一个模板,比用@babel/types去生成方便很多
    const temp = template(`
      if(something) {
        NORMAL_RETURN
      } else {
        return 'nothing'
      }
    `)
    const
 = path.node.body.body[0]
    const tempAst = temp({
      NORMAL_RETURN: returnNode
    })
    path.node.body.body[0] = tempAst
  }
}
traverse(ast, visitor)
const transformedCode = generate(ast).code
console.log(transformedCode)