【问题标题】:optimize rollup config to enable tree shaking优化汇总配置以启用树抖动
【发布时间】:2019-07-20 17:13:00
【问题描述】:

我想就如何构建一个易于使用且经过摇树优化的构建获得建议。我正在使用 rollup 来打包一个由多个组件组成的 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,在这种情况下它可能会在构建中复制(例如,一个外部使用版本和一个内部使用版本)。

我不知道如何进行优化。任何指针都非常受欢迎。

【问题讨论】:

    标签: javascript vue.js rollup


    【解决方案1】:

    就目前而言,我能找到的唯一有效解决方案是在 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.json 复制/粘贴到dist/cdnpm publish 中...这已集成到我们的 CI 任务中,因为它与汇总或构建,而不是发布。

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

    【讨论】:

    • 实际上rollup在这个问题之后不久就启用了对输入文件数组的支持。
    猜你喜欢
    • 1970-01-01
    • 2020-05-08
    • 1970-01-01
    • 2019-08-15
    • 1970-01-01
    • 2018-07-03
    • 2021-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多