babel-plugin-resolve-config-json

1.1.2-0 • Public • Published

babel-plugin-resolve-config-json

Build Status

Build Status

npm download

根据 jsconfig.json/tsonfig.json 的路径映射,通过 babel 自动转换模块路径,可以省去手动编写 webpackresolve.alias 配置以及解决 monorepo 中跨项目直接引用源码时多项目间的 tsconfig 的 path 的同名冲突问题

使用方法

这是一个 babel 插件

npm i -D babel-plugin-resolve-config-json
// babel配置
// 最好放在babel插件的第一位执行,也就是plugin数组的最后一位(babel plugin执行是逆序的)
const babelOptions = {
  presets: [],
  plugins: [
    [
      require.resolve('babel-plugin-resolve-config-json'),
      {
        isTypescript: true, // true时读取tsconfig.json,false时读取jsconfig.json。默认是false
        modules: [path.resolve(__dirname, `${projectRootPath}`)], // 默认是运行终端命令的目录。可以传递接收一个路径数组(支持正则或者字符串),表示哪些路径下的文件才需要经过该插件的处理
      },
    ],
  ],
}

为什么需要

1. 解决需要额外配置一份 webpack alias 的问题

在使用 typescript 的 webpack 项目中,为了避免手写../../../../的引用方法,我们经常会配置tsconfig.jsoncompilerOptions.pathsvscode去实现自动代码简单路径检索。除此之外,我们还需要配置webpackresolve.alias告诉webpack如何找到打包文件(目前很多脚手架如create-react-app其实会内置 tsconfig.json 到 webpack alias 的映射)

例如:

// jsconfig.json or tsconfig.json
{
  "compilerOptions": {
    "paths": {
      "Config/*": ["src/config/*"],
      "Components/*": ["src/components/*"],
      "Ducks/*": ["src/ducks/*"],
      "Shared/*": ["src/shared/*"],
      "App/*": ["src/*"]
    }
  }
}
// webpack
module.resolve = {
  alias: {
    Config: path.resolve(__dirname, '..', 'src', 'config'),
    Components: path.resolve(__dirname, '..', 'src', 'components'),
    Ducks: path.resolve(__dirname, '..', 'src', 'ducks'),
    Shared: path.resolve(__dirname, '..', 'src', 'shared'),
    App: path.join(__dirname, '..', 'src'),
  },
}

其实上面 webpack 这段代码也可以通过一个工具函数生成

// https://gist.github.com/nerdyman/2f97b24ab826623bff9202750013f99e

const { resolve } = require('path')

/**
 * Resolve tsconfig.json paths to Webpack aliases
 * @param  {string} tsconfigPath           - Path to tsconfig
 * @param  {string} webpackConfigBasePath  - Path from tsconfig to Webpack config to create absolute aliases
 * @return {object}                        - Webpack alias config
 */
function resolveTsconfigPathsToAlias({
  tsconfigPath = './tsconfig.json',
  webpackConfigBasePath = __dirname,
} = {}) {
  const { paths } = require(tsconfigPath).compilerOptions

  const aliases = {}

  Object.keys(paths).forEach((item) => {
    const key = item.replace('/*', '')
    const value = resolve(
      webpackConfigBasePath,
      paths[item][0].replace('/*', '').replace('*', '')
    )

    aliases[key] = value
  })

  return aliases
}

// webpack配置
module.exports = {
  // ...
  resolve: {
    // ...
    alias: resolveTsconfigPathsToAlias({
      tsconfigPath: '../tsconfig.json', // Using custom path
      webpackConfigBasePath: '../', // Using custom path
    }),
  },
}

而通过直接使用babel-plugin-resolve-config-json。只需要配置 typescript 的compilerOptions.paths,就可以直接让 babel loader 去进行处理,无需webpack再写一份 alias 配置就可以实现成功打!

原理上和babel-plugin-module-resolver差不多。babel-plugin-resolve-config-json的作用是为了直接通过编辑器的json配置处理,省去配置webpack的部分

2. 解决 monorepo 中跨项目直接引入源码时,不同项目都存在 tsconfig 的 paths 问题

假设在一个 monorepo 中,A 项目想直接通过直接引入源码的方式引入 B 项目中的代码,如果 B 项目用到了 tsconfig 的 paths 进行路径映射,直接这样引入 B 的代码肯定是打包失败的,因为 B 中的这个 paths 问题,A 的打包程序肯定是找不到的,这时候只需要使用本插件就可以解决这个打包问题。将 B 的路径传入 modules 的配置即可。

const babelOptions = {
  presets: [],
  plugins: [
    [
      require.resolve('babel-plugin-resolve-config-json'),
      {
        isTypescript: true,
        modules: [path.resolve(__dirname, `${projectRootPath}`, 'B的路径')],
      },
    ],
  ],
}

可靠吗

已经在日常线上项目打包使用很稳定(从 2019.9 月开始)。(如果有 bug,webpack 打包阶段会抛异常)。可参考单元测试中的样例

注意

tsconfig.jsoncompilerOptions.paths的 value 是一个数组,会依次查找模块,该插件只处理组字的第 0 项,而不会实现编辑器对于tsconfig的查找过程

单元测试

npm run test

已知问题

若使用webpack.HashedModuleIdsPlugin。打包 hash 受到项目存放路径不同的影响,转换成绝对路径的原因会导致打包产物 hash 可能不一致。若在 CI 机器上则无问题。

TODO: 多加一步绝对路径处理成当前文件的相对路径,能一定程度改善这个问题。或不使用webpack.HashedModuleIdsPlugin

Package Sidebar

Install

npm i babel-plugin-resolve-config-json

Weekly Downloads

131

Version

1.1.2-0

License

MIT

Unpacked Size

29 kB

Total Files

29

Last publish

Collaborators

  • flytam