# 文件 URLs

要在 JS 代码中引用文件 URL 引用,请使用 import.meta.ROLLUP_FILE_URL_referenceId 替换。这将生成依赖于输出格式的代码,并生成指向目标环境中发出的文件的 URL。请注意,除了 CommonJS 和 UMD 之外的所有格式都假定它们在浏览器环境中运行,其中 URL 和 document 可用。

以下示例将检测 .svg 文件的导入,将导入的文件作为资源发出,并返回它们的 URL,例如用作 img 标签的 src 属性:

function svgResolverPlugin() {
	return {
		name: 'svg-resolver',
		resolveId(source, importer) {
			if (source.endsWith('.svg')) {
				return path.resolve(path.dirname(importer), source);
			}
		},
		load(id) {
			if (id.endsWith('.svg')) {
				const referenceId = this.emitFile({
					type: 'asset',
					name: path.basename(id),
					source: fs.readFileSync(id)
				});
				return `export default import.meta.ROLLUP_FILE_URL_${referenceId};`;
			}
		}
	};
}

用法:

import logo from '../images/logo.svg';
const image = document.createElement('img');
image.src = logo;
document.body.appendChild(image);

有时,引用此静态资源的代码只会有条件地使用,如以下示例所示:

import logo from '../images/logo.svg';
if (COMPILER_FLAG) {
	const image = document.createElement('img');
	image.src = logo;
	document.body.appendChild(image);
}

如果插件将 COMPLIER_FLAG 替换为 false,那么我们将得到一个意外的结果:未引用的静态资源仍然会被发出但未使用。我们可以通过在调用 this.emitFile 时将 needsCodeReference 设置为 true 来解决这个问题,如下面的代码所示:

function svgResolverPlugin() {
	return {
		/* ... */
		load(id) {
			if (id.endsWith('.svg')) {
				const referenceId = this.emitFile({
					type: 'asset',
					name: path.basename(id),
					needsCodeReference: true,
					source: fs.readFileSync(id)
				});
				return `export default import.meta.ROLLUP_FILE_URL_${referenceId};`;
			}
		}
	};
}

现在,只有在代码中实际使用引用 import.meta.ROLLUP_FILE_URL_referenceId 时,静态资源才会添加到产物中。

类似于静态资源,发出的块也可以通过 import.meta.ROLLUP_FILE_URL_referenceId 从 JS 代码中引用。

以下示例将检测以 register-paint-worklet: 为前缀的导入,并生成必要的代码和单独的块以生成 CSS 绘制工作流。请注意,这仅适用于现代浏览器,并且仅在输出格式设置为 es 时才有效。

const REGISTER_WORKLET = 'register-paint-worklet:';

function registerPaintWorkletPlugin() {
	return {
		name: 'register-paint-worklet',
		load(id) {
			if (id.startsWith(REGISTER_WORKLET)) {
				return `CSS.paintWorklet.addModule(import.meta.ROLLUP_FILE_URL_${this.emitFile(
					{
						type: 'chunk',
						id: id.slice(REGISTER_WORKLET.length)
					}
				)});`;
			}
		},
		resolveId(source, importer) {
			// 我们去掉前缀,将所有内容解析为绝对 ID,
			// 然后再添加前缀。
			// 这样可以确保你可以使用相对导入来定义工作流
			if (source.startsWith(REGISTER_WORKLET)) {
				return this.resolve(
					source.slice(REGISTER_WORKLET.length),
					importer
				).then(resolvedId => REGISTER_WORKLET + resolvedId.id);
			}
			return null;
		}
	};
}

用法:

// main.js
import 'register-paint-worklet:./worklet.js';
import { color, size } from './config.js';
document.body.innerHTML += `<h1 style="background-image: paint(vertical-lines);">color: ${color}, size: ${size}</h1>`;

// worklet.js
import { color, size } from './config.js';
registerPaint(
	'vertical-lines',
	class {
		paint(ctx, geom) {
			for (let x = 0; x < geom.width / size; x++) {
				ctx.beginPath();
				ctx.fillStyle = color;
				ctx.rect(x * size, 0, 2, geom.height);
				ctx.fill();
			}
		}
	}
);

// config.js
export const color = 'greenyellow';
export const size = 6;

如果你构建上诉代码,则主块和工作块都将通过共享块从 config.js 共享代码。这使我们能够利用浏览器缓存来减少传输数据并加快加载工作块的速度。

Last Updated: 6/14/2023, 8:56:23 AM