transformers-js-demo / webpack.config.js
whackthejacker's picture
Upload 12 files
d470669 verified
import TerserPlugin from "terser-webpack-plugin";
import { fileURLToPath } from "url";
import path from "path";
import fs from "fs";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
/**
* Plugin to post-process build files. Required to solve certain issues with ESM module output.
* See https://github.com/webpack/webpack/issues/17121 for more information.
*
* @see https://webpack.js.org/contribute/writing-a-plugin/
*/
class PostBuildPlugin {
apply(compiler) {
compiler.hooks.done.tap('PostBuildPlugin', () => {
const dist = path.join(__dirname, 'dist');
const ORT_JSEP_FILE = 'ort-wasm-simd-threaded.jsep.mjs';
const ORT_BUNDLE_FILE = 'ort.bundle.min.mjs';
// 1. Remove unnecessary files
{
const file = path.join(dist, ORT_BUNDLE_FILE);
if (fs.existsSync(file)) fs.unlinkSync(file);
}
// 2. Copy unbundled JSEP file
{
const src = path.join(__dirname, 'node_modules/onnxruntime-web/dist', ORT_JSEP_FILE);
const dest = path.join(dist, ORT_JSEP_FILE);
fs.copyFileSync(src, dest);
}
// 3. Replace strings in certain files
{
const files = ['transformers.js', 'transformers.min.js'];
for (const file of files) {
const filePath = path.join(dist, file);
let content = fs.readFileSync(filePath, 'utf8');
content = content.replace(
// Replace all instances of `new URL("./", import.meta.url)` with `new URL(import.meta.url)`,
// as it causes several issues with build tools and bundlers.
//
// See the following issues for more information:
// - https://github.com/huggingface/transformers.js/issues/911
// - https://github.com/huggingface/transformers.js/issues/984
// - https://github.com/huggingface/transformers.js/issues/980
// - https://github.com/huggingface/transformers.js/issues/1021
// - https://github.com/huggingface/transformers.js/issues/1026
new RegExp('new URL\\(["\']\\.\\\/["\'],\\s*import\\.meta\\.url\\)', 'gm'),
"new URL(import.meta.url)",
);
fs.writeFileSync(filePath, content, 'utf8');
}
}
});
}
}
/**
* Helper function to create webpack configurations.
* @param {Object} options Options for creating a webpack target.
* @param {string} options.name Name of output file.
* @param {string} options.suffix Suffix of output file.
* @param {string} options.type Type of library.
* @param {string} options.ignoreModules The list of modules to ignore.
* @param {string} options.externalModules The list of modules to set as external.
* @param {Object[]} options.plugins List of plugins to use.
* @returns {import('webpack').Configuration} One webpack target.
*/
function buildConfig({
name = "",
suffix = ".js",
type = "module", // 'module' | 'commonjs'
ignoreModules = [],
externalModules = [],
plugins = [],
} = {}) {
const outputModule = type === "module";
const alias = Object.fromEntries(
ignoreModules.map((module) => [module, false]),
);
/** @type {import('webpack').Configuration} */
const config = {
mode: "development",
devtool: "source-map",
entry: {
[`transformers${name}`]: "./src/transformers.js",
[`transformers${name}.min`]: "./src/transformers.js",
},
output: {
filename: `[name]${suffix}`,
path: path.join(__dirname, "dist"),
library: {
type,
},
assetModuleFilename: "[name][ext]",
chunkFormat: "module",
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
test: new RegExp(`\\.min\\${suffix}$`),
// Do not bundle with comments.
// See https://webpack.js.org/plugins/terser-webpack-plugin/#remove-comments for more information.
terserOptions: {
output: {
comments: false,
},
},
extractComments: false,
}),
],
},
experiments: {
outputModule,
},
resolve: { alias },
externals: externalModules,
// Development server
devServer: {
static: {
directory: __dirname,
},
port: 8080,
},
plugins,
};
if (outputModule) {
config.module = {
parser: {
javascript: {
importMeta: false,
},
},
};
} else {
config.externalsType = "commonjs";
}
return config;
}
// Do not bundle onnxruntime-web when packaging for Node.js.
// Instead, we use the native library (onnxruntime-node).
const NODE_IGNORE_MODULES = ["onnxruntime-web"];
// Do not bundle the following modules with webpack (mark as external)
// NOTE: This is necessary for both type="module" and type="commonjs",
// and will be ignored when building for web (only used for node/deno)
const NODE_EXTERNAL_MODULES = [
"onnxruntime-node",
"sharp",
"fs",
"path",
"url",
];
// Web-only build
const WEB_BUILD = buildConfig({
type: "module",
plugins: [new PostBuildPlugin()],
});
// Node-compatible builds
const NODE_BUILDS = [
buildConfig({
suffix: ".mjs",
type: "module",
ignoreModules: NODE_IGNORE_MODULES,
externalModules: NODE_EXTERNAL_MODULES,
}),
buildConfig({
suffix: ".cjs",
type: "commonjs",
ignoreModules: NODE_IGNORE_MODULES,
externalModules: NODE_EXTERNAL_MODULES,
}),
];
// When running with `webpack serve`, only build the web target.
const BUILDS = process.env.WEBPACK_SERVE
? [WEB_BUILD]
: [WEB_BUILD, ...NODE_BUILDS];
export default BUILDS;