Skip to content

inlineCommonChunks: it's the chunks that get inlined not the modules #7

Description

@hyfdev

Prevously in rolldown/rolldown#10693, I was thinking unifying __share and __esm into the same thing, because:

  • __share and __esm both "wrap" the code
  • They both delay the execuion timing to call-time

Reasoning with these things, it seems intuitive to think of __share and __esm are similar thing with minor differences.

Also with thinking #5, I initially think wrappers in wrappers(see below per chunk example) output just doesn't feel right. It makes the execution model more complicated, which isn't a good signal.

With __esm wrappers in __share wrappers, you need to think that before calling some initXXX, you should make sure calling __share_require(...) to execute the body code of __share so those __esm calls get executed.

But then I found that isn't it intuitive you need to execute the "chunk" code if your code relies on the chunk. So it does make the execution model more complicated than the current one describled in #5. But it's sound.

Conclusion

  • The current direction is inlining "chunks" not "modules" in the chunks. So the output will look like // Per-chunk entry-b.js in the below example
  • strictExecutionOrder would be enabled/required for using inlineCommonChunks
  • Current direction gives the more optimal output
    • Inside of __share wrapper, modules are still scoped hoisted. This can't be done(or much limited) compared to module level approach
    • With strictExecutionOrder: true, multiple __share wrappers can always merge to one __share wrapper

Example

Input

// shared.js
globalThis.order ??= []
globalThis.order.push('shared')

export function mark(name) {
  globalThis.order.push(name)
}

// config.js
import { mark } from './shared.js'

mark('config')

// client.js
import './config.js'
import { mark } from './shared.js'

mark('client')

// locale.js
import { mark } from './shared.js'

mark('locale')

// ui.js
import './locale.js'
import { mark } from './shared.js'

mark('ui')

// entry-a.js
import './config.js'
import './client.js'

console.log(globalThis.order.join(','))
// shared,config,client

// entry-b.js
import './config.js'
import './locale.js'
import './client.js'
import './ui.js'

console.log(globalThis.order.join(','))
// shared,config,locale,client,ui

// entry-c.js
import './locale.js'
import './ui.js'

console.log(globalThis.order.join(','))
// shared,locale,ui
COMMON-ABC.js = [shared.js]
COMMON-AB.js = [config.js, client.js]
COMMON-BC.js = [locale.js, ui.js]

entry-a.js -> COMMON-AB.js -> COMMON-ABC.js

entry-b.js -> COMMON-AB.js -> COMMON-ABC.js
           -> COMMON-BC.js -> COMMON-ABC.js

entry-c.js -> COMMON-BC.js -> COMMON-ABC.js
// COMMON-ABC.js

function mark(name) {
  globalThis.order.push(name)
}

const init_shared = __esmMin(() => {
  globalThis.order ??= []
  globalThis.order.push('shared')
})

export {
  init_shared,
  mark,
}
// Per-module entry-b.js

import {
  init_shared,
  mark,
} from './COMMON-ABC.js'

__share('config.js', module => {
  const init_config = __esmMin(() => {
    init_shared()
    mark('config')
  })

  module.exports = { init_config }
})

__share('client.js', module => {
  const init_client = __esmMin(() => {
    __share_require('config.js').init_config()
    mark('client')
  })

  module.exports = { init_client }
})

__share('locale.js', module => {
  const init_locale = __esmMin(() => {
    init_shared()
    mark('locale')
  })

  module.exports = { init_locale }
})

__share('ui.js', module => {
  const init_ui = __esmMin(() => {
    __share_require('locale.js').init_locale()
    mark('ui')
  })

  module.exports = { init_ui }
})

const config = __share_require('config.js')
const locale = __share_require('locale.js')
const client = __share_require('client.js')
const ui = __share_require('ui.js')

config.init_config()
locale.init_locale()
client.init_client()
ui.init_ui()
// Per-chunk entry-b.js

import {
  init_shared,
  mark,
} from './COMMON-ABC.js'

__share('COMMON-AB.js', module => {
  const init_config = __esmMin(() => {
    init_shared()
    mark('config')
  })

  const init_client = __esmMin(() => {
    init_config()
    mark('client')
  })

  module.exports = {
    init_config,
    init_client,
  }
})

__share('COMMON-BC.js', module => {
  const init_locale = __esmMin(() => {
    init_shared()
    mark('locale')
  })

  const init_ui = __esmMin(() => {
    init_locale()
    mark('ui')
  })

  module.exports = {
    init_locale,
    init_ui,
  }
})

const commonAb = __share_require('COMMON-AB.js')
const commonBc = __share_require('COMMON-BC.js')

commonAb.init_config()
commonBc.init_locale()
commonAb.init_client()
commonBc.init_ui()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions