webpack
webpack copied to clipboard
Allow public path to be a function
Feature request
Allow the public path to be a function.
What is the expected behavior?
It should call the function everytime instead of +.
What is motivation or use case for adding/changing the behavior?
https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources
There is an option called "use_dynamic_url" in Chrome extension.
Normally, resources can be accessed via URLs like chrome-extension://odhaijconicohjickedigmojjmeblalp/my-file.js, but with this option on (this options improves security and privacy), it has to be chrome.runtime.getURL('my-file.js'), and the return URL becomes chrome-extension://21f06455-6875-452b-8132-01268c50ba0e/my-file.js where the UUID is random every time.
It will be easier to support this use case in a plugin (https://github.com/awesome-webextension/webpack-target-webextension/issues/47) if the public path can be a function.
How should this be implemented in your opinion?
Add a new webpack internal function:
__webpack__require__.xxx = function (path) {
if (typeof __webpack_require__.p == 'function') return __webpack_require__.p(path)
return __webpack_require.p + path
}
And replace all direct use of RuntimeGlobals.publicPath to call this helper function.
Are you willing to work on this yourself? yes
Unfortunately this is not possible, this option is only for calculation during bundling time (i.e. it can be string or function but only in bundling time) and used to find relative paths and for dev server to understand which URLs need to be handled, webpack is not only about JS, Also we support and CSS and HTML and etc there it is impossible.
This will also most likely break other plugins that expect this to be a string, especially those aimed at runtime changes.
the only option is to try to solve it at the level of plugins and hooks... But we have too many hardcoded + in the code
But I see what you're trying to solve.
That is, we need to solve this so that the code and plugins all work, when you have the code in custom plugin like this - ${RuntimeGlobals.publicPath} + ${myCustomAsset};
the only option is to try to solve it at the level of plugins and hooks... But we have too many hardcoded + in the code
I searched RuntimeGlobals.publicPath and there are only 40. If you can suggest the API shape, I'm willing to implement it! Thanks!
@Jack-Works
I searched RuntimeGlobals.publicPath and there are only 40.
The main problem is that our API is used by other plugins too,
so maybe we need ${RuntimeGlobals.dynamicPublicPath}(${RuntimeGlobals.publicPath} + ${myCustomAsset});
Maybe even a helper - which understands that we want to generate a dynamic public path, if yes, generate above, if not return ${RuntimeGlobals.publicPath} + ${myCustomAsset}
@alexander-akait I would like to create a PR. But I have two solutions for this. I can't decide which is better.
- add a new option called dynamicPublicPath.
- Pros it runs only at runtime. it will not affect the publicPath option.
- Cons the number of options has increased.
- change the internal logic of publicPath.
- Pros No new options are added.
- Cons calculation at runtime instead of bundling time. But for functions that don't want to return the difference value for each run, it may also affect the performance.
Me too, I'm willing to implement this but I'm not sure how
@sapenlei @Jack-Works My idead
- Add
__webpack_dynamic_public_path__like https://github.com/webpack/webpack/blob/main/lib/APIPlugin.js#L37 - Now we have
RuntimeGlobals.dynamicPublicPath - If
RuntimeGlobals.dynamicPublicPathis existing inruntimeRequirements(https://github.com/webpack/webpack/blob/main/lib/asset/AssetGenerator.js#L431C4-L431C23) we generate something like:
assetPath = runtimeRequirements.has(RuntimeGlobals.dynamicPublicPath)
? runtimeTemplate.generateFunction(RuntimeGlobals.dynamicPublicPath, runtimeTemplate.concatenation({ expr: RuntimeGlobals.publicPath }, filename)))
: runtimeTemplate.concatenation({ expr: RuntimeGlobals.publicPath }, filename));
This is a rough pseudo code to show the idea, maybe we can even improve the logic and implement runtimeTemplate.generatePublicPath(filename) which will encapsulate this logic in itself, and in the future will allow you to reuse it and add more logic if necessary
This approach will allow you to avoid new options, and plugins can simply use runtimeRequirements.add(RuntimeGlobals.dynamicPublicPath), devs will be able to override this using __webpack_dynamic_public_path__
assetPath = runtimeRequirements.has(RuntimeGlobals.dynamicPublicPath) ? runtimeTemplate.generateFunction(RuntimeGlobals.dynamicPublicPath, runtimeTemplate.concatenation({ expr: RuntimeGlobals.publicPath }, filename))) : runtimeTemplate.concatenation({ expr: RuntimeGlobals.publicPath }, filename));
I have a question. What's the way for a plugin to access the runtimeRequirements here and add RuntimeGlobals.dynamicPublicPath? I've looked at the existing hooks, and their trigger time seems to be later than AssetGenerator. Maybe I'm missing something.
Since the hooks you're observing are triggered after the AssetGenerator, we need a way to intervene earlier in the build process. I think we can use Compilation.hooks to access and modify runtime requirements. The compilation object allow us to manipulate runtime requirements.
@inottn Plugin can use additionalTreeRuntimeRequirements hook to add it
@inottn Plugin can use
additionalTreeRuntimeRequirementshook to add it
I tested it, and it seems that the execution time of additionalTreeRuntimeRequirements.call is later than _getAssetPathWithInfo.
Introducing webpack_dynamic_public_path as a global runtime function might help
This issue had no activity for at least three months.
It's subject to automatic issue closing if there is no activity in the next 15 days.
bump