首页 > 解决方案 > 优化汇总配置以启用摇树

问题描述

我想就如何构建一个方便使用和摇树优化的构建提供建议。我正在使用汇总来打包由多个组件组成的 UI 库。

我的架构是:

/src
  /index.js
  /components
    /index.js
    /component1
      /index.js
      /Comp.vue
    ...
    /componentN
      /index.js
      /Comp.vue
  /directives
    /index.js
    /directive1
      /index.js
    ...
    /directiveN
      /index.js

src/components/index.js看起来像

export { default as Comp1 } from './component1
...
export { default as CompN } from './componentN

src/directives/index.js看起来像

export { default as Directive1 } from './directive1
...
export { default as DirectiveN } from './directiveN

每个内部index.js只是为了方便的绑定,例如

import Comp from './Comp.vue'
export default Comp`

最后,src/index.js将收集所有内容:

import { * as components } from './components'
import { * as directives } from './directives'

export { components, directives }

构建时,汇总配置如下所示:

{
  input: 'src/index.js',
  output: {
    file: 'dist/lib.esm.js',
    format: 'esm',
}

(当然我要避免所有的编译丑化插件,我认为它们会成为这个问题的噪音)

所以这个构建看起来不错,并且有效,但是......

  1. 使用起来非常不方便:
import { components } from 'lib'
const { Comp1 } = components
  1. 这种结构可能在使用时也破坏了树抖动,因为我们只在需要时才导入完整的components对象。Comp1

我知道我不应该是关心摇树的人,而是提供一个支持摇树的库,这就是它的意义所在。当使用最简单的@vue/cli 模板测试我的构建时,完整的库被导入,甚至@vue/cli 声称已经启用了开箱即用的 webpack-treeshaking 功能。

我不介意构建单独的文件而不是一个大的 esm 构建,但据我所知,一个带有摇树的文件构建是可能的。我担心构建单独的文件是CompA内部需要CompB,如果用户也需要CompB,在这种情况下,它可能会在构建中重复(例如,一个外部使用版本和一个内部使用版本)。

我对如何进行优化一无所知。任何指针都受到高度欢迎。

标签: javascriptvue.jsrollup

解决方案


就目前而言,我能找到的唯一有效解决方案是在文件夹内的同一树结构中单独构建所有dist/文件。我决定构建文件以提供 Vue 文件格式样式块,而无需最终消费者进一步构建或配置。

构建后看起来像这样:

/src
  /index.js
  /components
    /index.js
    /component1
      /index.js
      /Comp.vue
    ...
    /componentN
      /index.js
      /Comp.vue
  /directives
    /index.js
    /directive1
      /index.js
    ...
    /directiveN
      /index.js

/dist
  /index.js
  /components
    /index.js
    /component1
      /index.js
    ...
    /componentN
      /index.js
  /directives
    /index.js
    /directive1
      /index.js
    ...
    /directiveN
      /index.js

我创建了一个小的递归函数来查找所有“index.js”并将这个列表与汇总多入口点功能一起使用。希望汇总创建所有子文件夹,因此不需要检查或mkdir -p.

// shorthand utility for 'find all files recursive matching regexp (polyfill for webpack's require.context)'
const walk = (directory, regexp) => {
  let files = readdirSync(directory)

  if (directory.includes('/examples'))
    return []

  return files.reduce((arr, file) => {
    let path = `${directory}/${file}`
    let info = statSync(path)

    if (info.isDirectory())
      return arr.concat(walk(path, regexp))
    else if (regexp.test(file))
      return arr.concat([path])
    else
      return arr
  }, [])
}

// ...

const esm = walk(`${__dirname}/src`, /^index\.js$/)
  .map(file => ({
    input: file,

    output: {
      format: 'esm',
      file: file.replace(`${__dirname}/src`, CONFIG.module)
    },
    ...
  }))

该过程的最后一部分是复制/粘贴package.jsondist/cd其中和npm publish从中... 这已集成到我们的 CI 任务中,因为它与汇总或构建没有直接关系,而是与发布相关。

这并不完美,但由于缺乏输入,这是我发现的唯一方法。我希望它会帮助某人。


推荐阅读