javascriptnode.jswebpackwebpack-plugin

can Webpack.DefinePlugin.runtimeValue get the module's entry?


enter image description here

just like this, use DefinePlugin to define global var ECZN for my app with webpack runtimeValue.

and... the WebpackModuleInfo is actually from the file where i refer ECZN, but i just get the module file path, not the Entry ...

so, can i get the entry info for the runtimeValue's context in order to set different var value for my multi html page app ?


text code:

      new Webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(WEBPACK_NODE_ENV),
        development: JSON.stringify(WEBPACK_NODE_ENV_DEV),
        production: JSON.stringify(WEBPACK_NODE_ENV_PROD),
        ECZN: Webpack.DefinePlugin.runtimeValue((ctx) => {
          console.log('WebpackModuleInfo :: ', ctx.module);
          // @ts-ignore webpack.d.ts doesn't define resource, but it exists on ctx.module acutally
          const moduleResource: unknown = ctx.module.resource;
          if (typeof moduleResource === 'string' && moduleResource.length) {
            const absPathFromCwd = path.relative(cwdResolve('.'), moduleResource);

            return JSON.stringify(absPathFromCwd);
          }
          // throw error if not found
          throw new Error('dynamic');
        }),
      })

i had found some solutions :

  1. make app to have multi webpack config to create multi instance like this: https://github.com/webpack/webpack/issues/5546 (performance warning)
  2. just use the moduleResource as reference to define var Eczn (it's not precisely)

Solution

  • I can think of three solutions to get the entry point that contains the import chain to module. I'll list all of them since I'm not sure which one is best for your case. Webpack doesn't document these objects, so it's hard to say which is the correct method.

    Note that I found this question when researching in the context of web workers and parser object.


    module.parser.state.compilation.entries

    module.parser.state.compilation.entries is an array. I'm guessing because a module can have multiple entry points. I'm not sure how to determine the current entry point with this method since I don't have multiple entry points to test. Test it out in a debugger.

    For workers:

    module.parser.state.compilation.entries[0].resource === '/.../moduleEntryPoint.js'
    

    For files along webpack config entrypoints:

    module.parser.state.compilation.entries[0].name === 'main'
    
    # Can have array of `dependencies` if your webpack config entrypoint is an array
    module.parser.state.compilation.entries[0].dependencies[*].module.resource === '/.../moduleEntryPoint.js'
    
    module.parser.state.compilation.entries[0].dependencies[*].request === '/.../moduleEntryPoint.js'
    

    Parse compilation.name

    It would look something like this:

    For workers:

    module.parser.state.compilation.name ===
    'worker-loader /.../node_modules/babel-loader/lib/index.js??ref--5!/.../node_modules/source-map-loader/index.js!/.../moduleEntryPoint.js'
    

    You can use string manipulation to grab the entry point.

    For files along webpack config entrypoints:

    module.parser.state.compilation.name === 'client'
    

    loop through module.issuer until null

    For workers:

    while (module.issuer) {
      module = module.issuer
    }
    module.resource === '/.../moduleEntryPoint.js'
    

    For files along webpack config entrypoints:

    while (module.issuer) {
      module = module.issuer
    }
    
    module.parser.state.compilation.entries[0].name === 'main'
    
    # Can have array of `dependencies` if your webpack config entrypoint is an array
    module.parser.state.compilation.entries[0].dependencies[*].module.resource === '/.../moduleEntryPoint.js'
    
    module.parser.state.compilation.entries[0].dependencies[*].request === '/.../moduleEntryPoint.js'
    

    If there is only one entry point, the issuer module === module.parser.state.compilation.entries[0].