Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: access to compilation.assetsInfo in compilation.hooks.processAssets.tap #7033

Open
iusesoftware opened this issue Jul 3, 2024 · 7 comments
Labels
feat New feature or request

Comments

@iusesoftware
Copy link

What problem does this feature solve?

Hi! I was trying to migrate my webpack v5 setup with several custom-built webpack plugins to Rspack v1.0.0-alpha.0, but faced a blocker:
One of my custom webpack plugins uses the assets info metadata in the processAssets compilation hook, but it's undefined in Rspack.

My use case:
Besides regular webpack entries, my setup also processes pre-webpack legacy JS, CSS, and image files added via CopyWebpackPlugin: their content hash gets added into the file name, and on processAssets I generate a map of original sourceFilenames to the new paths, which is then used by a non-Node.js server to replace original file references with the ones that have content hash in them.

Is there another way to get the assets info metadata in Rspack?
If not, is it something you can add?

Thank you.

What does the proposed API of configuration look like?

Example:

compilation.hooks.processAssets.tap(
  {
    /** … */
  },
  (assets) => {
    Object.entries(assets).forEach(([pathname, source]) => {
      const assetInfo = compilation.assetsInfo.get(pathname);
      // @todo: do something with "pathname", "source" and "assetInfo"
    });
  }
);

See https://webpack.js.org/api/compilation-hooks/#assets-info

@iusesoftware iusesoftware added feat New feature or request pending triage The issue/PR is currently untouched. labels Jul 3, 2024
@wxiaoyun
Copy link
Contributor

wxiaoyun commented Jul 4, 2024

If you are trying to append and access additional information to AssetInfo object across compilation stages, please use compilation.updateAsset to update assetInfo, compilation.getAsset or compilation.getAssets to retrieve assetInfo.

These getters and setters are necessary for bidirectional conversion between Js Object and their corresponding Rust structs under the hood. Otherwise, only knownAssetInfo will be persisted across compilation stages:

image

Let me know if this helped

@iusesoftware
Copy link
Author

This helped, thank you. I was able to move forward a little bit.

1) Do you know if there is a way to replace compilation.assets[ filePath ].source()?
I searched for updateAsset in the repo and found that there is also getAssetSource, but seems like it's internal only.

2) Also, I wasn't able to confirm this fully, because I'm getting Process finished with exit code -1073741571 (0xC00000FD) (stack overflow?).
I understand this is probably not related, but may be you know what may be causing this?

@wxiaoyun
Copy link
Contributor

wxiaoyun commented Jul 4, 2024

  1. Do you know if there is a way to replace compilation.assets[ filePath ].source()? I searched for updateAsset in the repo and found that there is also getAssetSource, but seems like it's internal only.

Calling compilation.getAsset(<name>) or compilation.getAssets() gives you Asset object with source

	getAssets(): ReadonlyArray<Asset> {
		const assets = this.#inner.getAssets();

		return assets.map(asset => {
			return Object.defineProperties(asset, {
				info: {
					value: JsAssetInfo.__from_binding(asset.info)
				},
				source: {
					get: () => this.__internal__getAssetSource(asset.name)
				}
			}) as unknown as Asset;
		});
	}

@wxiaoyun
Copy link
Contributor

wxiaoyun commented Jul 4, 2024

  1. Also, I wasn't able to confirm this fully, because I'm getting Process finished with exit code -1073741571 (0xC00000FD) (stack overflow?). I understand this is probably not related, but may be you know what may be causing this?

I am not sure what it means. Can you create a minimal reproduction that triggers this error?

@iusesoftware
Copy link
Author

  1. Do you know if there is a way to replace compilation.assets[ filePath ].source()? I searched for updateAsset in the repo and found that there is also getAssetSource, but seems like it's internal only.

Calling compilation.getAsset(<name>) or compilation.getAssets() gives you Asset object with source

	getAssets(): ReadonlyArray<Asset> {
		const assets = this.#inner.getAssets();

		return assets.map(asset => {
			return Object.defineProperties(asset, {
				info: {
					value: JsAssetInfo.__from_binding(asset.info)
				},
				source: {
					get: () => this.__internal__getAssetSource(asset.name)
				}
			}) as unknown as Asset;
		});
	}

One custom plugin emits a new asset with:

const fileContents = JSON.stringify( fileListJson );

compilation.emitAsset( fullPath, new compiler.webpack.sources.RawSource( fileContents ) );

And in another custom plugin I tried:

compilation.getAsset( filePath ).source(); // didn't work
compilation.getAsset( filePath ).source.get(); // didn't work
compilation.getAsset( filePath ).source.toString(); // didn't work

Only this worked, but seems like it's a band-aid:

const fileMapSource = compilation.getAsset( filePath ).source._valueAsString; // did work

Its usage is:

const fileMap = JSON.parse( fileMapSource );

I'm on v1.0.0-alpha.2 now.

@iusesoftware
Copy link
Author

Is there access to compilation.valueCacheVersions?

I only found this:

My usage in the same custom plugin:

const foundAsset = findAsset( pathInMap, compilation.assetsInfo );

if ( foundAsset ) {
    let assetPathPrefix = '';

    for ( const [ key, value ] of compilation.valueCacheVersions ) {
        // @todo Find less error-prone way.
        if ( key.includes( 'webpack/DefinePlugin process.env.ASSET_PATH' ) ) {
            assetPathPrefix = value
                // “/” gets (re)added later
                // @todo This is all dirty. Find a better way.
                .replace( '/', '' )
                .replace( /"/gu, '' );
        }
    }

    filePath = `${ assetPathPrefix }${ foundAsset }`;
}

@h-a-n-a
Copy link
Collaborator

h-a-n-a commented Jul 9, 2024

And in another custom plugin I tried:

compilation.getAsset( filePath ).source(); // didn't work
compilation.getAsset( filePath ).source.get(); // didn't work
compilation.getAsset( filePath ).source.toString(); // didn't work

Only this worked, but seems like it's a band-aid:

const fileMapSource = compilation.getAsset( filePath ).source._valueAsString; // did work

You were using the wrong API. Check out webpack-sources.

@jerrykingxyz jerrykingxyz removed the pending triage The issue/PR is currently untouched. label Jul 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants