mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-14 01:37:26 +00:00
Rollup build
This commit is contained in:
175
lib/client-bundle-plugin.js
Normal file
175
lib/client-bundle-plugin.js
Normal file
@@ -0,0 +1,175 @@
|
||||
/**
|
||||
* Copyright 2020 Google Inc. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import rollup from 'rollup';
|
||||
|
||||
const prefix = 'client-bundle:';
|
||||
const entryPathPlaceholder = 'CLIENT_BUNDLE_PLUGIN_ENTRY_PATH';
|
||||
const importsPlaceholder = 'CLIENT_BUNDLE_PLUGIN_IMPORTS';
|
||||
const allSrcPlaceholder = 'CLIENT_BUNDLE_PLUGIN_ALL_SRC';
|
||||
|
||||
export function getDependencies(clientOutput, item) {
|
||||
const crawlDependencies = new Set([item.fileName]);
|
||||
|
||||
for (const fileName of crawlDependencies) {
|
||||
const chunk = clientOutput.find((v) => v.fileName === fileName);
|
||||
|
||||
for (const dep of chunk.imports) {
|
||||
crawlDependencies.add(dep);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't add self as dependency
|
||||
crawlDependencies.delete(item.fileName);
|
||||
|
||||
return [...crawlDependencies];
|
||||
}
|
||||
|
||||
export default function (inputOptions, outputOptions, resolveFileUrl) {
|
||||
let cache;
|
||||
let entryPointPlaceholderMap;
|
||||
let exportCounter;
|
||||
let clientBundle;
|
||||
let clientOutput;
|
||||
|
||||
return {
|
||||
name: 'client-bundle',
|
||||
buildStart() {
|
||||
entryPointPlaceholderMap = new Map();
|
||||
exportCounter = 0;
|
||||
},
|
||||
async resolveId(id, importer) {
|
||||
if (!id.startsWith(prefix)) return null;
|
||||
|
||||
const realId = id.slice(prefix.length);
|
||||
const resolveResult = await this.resolve(realId, importer);
|
||||
// Add an additional .js to the end so it ends up with .js at the end in the _virtual folder.
|
||||
if (resolveResult) return prefix + resolveResult.id + '.js';
|
||||
// This Rollup couldn't resolve it, but maybe the inner one can.
|
||||
return id + '.js';
|
||||
},
|
||||
load(id) {
|
||||
if (!id.startsWith(prefix)) return;
|
||||
|
||||
const realId = id.slice(prefix.length, -'.js'.length);
|
||||
|
||||
exportCounter++;
|
||||
|
||||
entryPointPlaceholderMap.set(exportCounter, realId);
|
||||
|
||||
return [
|
||||
`export default import.meta.${entryPathPlaceholder + exportCounter};`,
|
||||
`export const imports = import.meta.${
|
||||
importsPlaceholder + exportCounter
|
||||
};`,
|
||||
`export const allSrc = import.meta.${
|
||||
allSrcPlaceholder + exportCounter
|
||||
};`,
|
||||
].join('\n');
|
||||
},
|
||||
async buildEnd(error) {
|
||||
const entryPoints = [...entryPointPlaceholderMap.values()];
|
||||
// The static-build is done, so now we can perform our client build.
|
||||
// Exit early if there's nothing to build.
|
||||
if (error || entryPoints.length === 0) return;
|
||||
|
||||
clientBundle = await rollup.rollup({
|
||||
...inputOptions,
|
||||
cache,
|
||||
input: entryPoints,
|
||||
});
|
||||
|
||||
cache = clientBundle.cache;
|
||||
},
|
||||
async renderStart(staticBuildOutputOpts) {
|
||||
// The static-build has started generating output, so we can do the same for our client build.
|
||||
// Exit early if there's nothing to build.
|
||||
if (!clientBundle) return;
|
||||
const copiedOutputOptions = {
|
||||
assetFileNames: staticBuildOutputOpts.assetFileNames,
|
||||
};
|
||||
clientOutput = (
|
||||
await clientBundle.generate({
|
||||
...copiedOutputOptions,
|
||||
...outputOptions,
|
||||
})
|
||||
).output;
|
||||
},
|
||||
resolveImportMeta(property, { moduleId, format }) {
|
||||
// Pick up the placeholder exports we created earlier, and fill in the correct details.
|
||||
let num = undefined;
|
||||
|
||||
if (property.startsWith(entryPathPlaceholder)) {
|
||||
num = Number(property.slice(entryPathPlaceholder.length));
|
||||
} else if (property.startsWith(importsPlaceholder)) {
|
||||
num = Number(property.slice(importsPlaceholder.length));
|
||||
} else if (property.startsWith(allSrcPlaceholder)) {
|
||||
num = Number(property.slice(allSrcPlaceholder.length));
|
||||
} else {
|
||||
// This isn't one of our placeholders.
|
||||
return;
|
||||
}
|
||||
|
||||
const id = entryPointPlaceholderMap.get(num);
|
||||
const clientEntry = clientOutput.find(
|
||||
(item) => item.facadeModuleId === id,
|
||||
);
|
||||
|
||||
if (property.startsWith(entryPathPlaceholder)) {
|
||||
return resolveFileUrl({
|
||||
fileName: clientEntry.fileName,
|
||||
moduleId,
|
||||
format,
|
||||
});
|
||||
}
|
||||
|
||||
const dependencies = getDependencies(clientOutput, clientEntry);
|
||||
|
||||
if (property.startsWith(allSrcPlaceholder)) {
|
||||
return JSON.stringify(
|
||||
[clientEntry.code, ...dependencies.map((d) => d.code)].join(';'),
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
'[' +
|
||||
dependencies
|
||||
.map((item) => {
|
||||
const entry = clientOutput.find((v) => v.fileName === item);
|
||||
|
||||
return resolveFileUrl({
|
||||
fileName: entry.fileName,
|
||||
moduleId,
|
||||
format: outputOptions.format,
|
||||
});
|
||||
})
|
||||
.join(',') +
|
||||
']'
|
||||
);
|
||||
},
|
||||
async generateBundle(options, bundle) {
|
||||
// Exit early if there's nothing to build.
|
||||
if (!clientOutput) return;
|
||||
// Copy everything from the client bundle into the main bundle.
|
||||
for (const clientEntry of clientOutput) {
|
||||
// Skip if the file already exists
|
||||
if (clientEntry.fileName in bundle) continue;
|
||||
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
source: clientEntry.code || clientEntry.source,
|
||||
fileName: clientEntry.fileName,
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user