cvat/cvat-ui/webpack.config.js

213 lines
8.0 KiB
JavaScript
Raw Permalink Normal View History

2025-09-16 01:19:40 +00:00
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const Dotenv = require('dotenv-webpack');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = (env) => {
const defaultAppConfig = path.join(__dirname, 'src/config.tsx');
const defaultPlugins = ['plugins/sam'];
const sourceMapsDisabled = (process.env.DISABLE_SOURCE_MAPS || 'false').toLocaleLowerCase() === 'true';
const appConfigFile = process.env.UI_APP_CONFIG ? process.env.UI_APP_CONFIG : defaultAppConfig;
const pluginsList = process.env.CLIENT_PLUGINS ? [...defaultPlugins, ...process.env.CLIENT_PLUGINS.split(':')]
.map((s) => s.trim()).filter((s) => !!s) : defaultPlugins;
const sourceMapsToken = process.env.SOURCE_MAPS_TOKEN || '';
const transformedPlugins = pluginsList
.filter((plugin) => !!plugin).reduce((acc, _path, index) => ({
...acc,
[`plugin_${index}`]: {
dependOn: 'cvat-ui',
// path can be absolute, in this case it is accepted as is
// also the path can be relative to cvat-ui root directory
import: path.isAbsolute(_path) ? _path : path.join(__dirname, _path, 'src', 'ts', 'index.tsx'),
},
}), {});
console.log('Source maps: ', sourceMapsDisabled ? 'disabled' : 'enabled');
console.log('List of plugins: ', Object.values(transformedPlugins).map((plugin) => plugin.import));
const host = process.env.CVAT_UI_HOST ?? 'localhost';
const port = process.env.CVAT_UI_PORT ?? 3000;
return {
target: 'web',
mode: 'production',
devtool: sourceMapsDisabled ? false : 'source-map',
entry: {
'cvat-ui': './src/index.tsx',
...transformedPlugins,
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'assets/[name].[contenthash].min.js',
publicPath: '/',
},
devServer: {
host,
port,
compress: false,
client: {
overlay: false,
webSocketURL: 'ws://0.0.0.0:0/ws',
},
historyApiFallback: true,
static: {
directory: path.join(__dirname, 'dist'),
},
headers: {
// to enable SharedArrayBuffer and ONNX multithreading
// https://cloudblogs.microsoft.com/opensource/2021/09/02/onnx-runtime-web-running-your-machine-learning-model-in-browser/
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'credentialless',
},
proxy: [{
context: (param) =>
param.match(
/\/api\/.*|analytics\/.*|static\/.*|admin(?:\/(.*))?.*|profiler(?:\/(.*))?.*|documentation\/.*|django-rq(?:\/(.*))?/gm,
),
target: env && env.API_URL,
secure: false,
changeOrigin: true,
onProxyReq: (proxyReq) => {
proxyReq.setHeader('X-FORWARDED-HOST', `${host}:${port}`);
},
}],
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
fallback: {
fs: false,
},
alias: {
config$: appConfigFile,
// when import svg modules
// the loader transforms their to modules with JSX code
// and adds 'import React from "react";'
// in plugins it leads to errors because they must import '@modules/react'
// so, this alias added to fix it
react: '@modules/react',
'@root': path.resolve(__dirname, 'src'),
'@modules': path.resolve(__dirname, '..', 'node_modules'),
},
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
use: {
loader: 'babel-loader',
options: {
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-optional-chaining',
[
'import',
{
libraryName: 'antd',
},
],
],
presets: ['@babel/preset-env', '@babel/preset-react', '@babel/typescript'],
sourceType: 'unambiguous',
},
},
},
{
test: /\.(css|scss)$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
},
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
[
'postcss-preset-env', {},
],
],
},
},
},
'sass-loader',
],
},
{
test: /\.svg$/,
exclude: /node_modules/,
use: [
'babel-loader',
{
loader: 'react-svg-loader',
options: {
svgo: {
plugins: [{ pretty: true }, { cleanupIDs: false }],
},
},
},
],
},
{
test: /\.(png|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
parser: {
javascript: {
exportsPresence: 'error',
},
},
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
inject: 'body',
}),
new Dotenv({
systemvars: true,
}),
new CopyPlugin({
patterns: [
{
from: '../cvat-data/src/ts/3rdparty/avc.wasm',
to: 'assets/3rdparty/',
},
{
from: '../node_modules/onnxruntime-web/dist/*.wasm',
to : 'assets/[name][ext]',
},
{
from: 'src/assets/opencv_4.8.0.js',
to : 'assets/opencv_4.8.0.js',
},
{
from: 'src/assets/*.png',
to : 'assets/[name][ext]',
},
{
from: 'plugins/**/assets/*.(onnx|js)',
to : 'assets/[name][ext]',
}
],
}),
...(!sourceMapsDisabled && sourceMapsToken ? [new webpack.SourceMapDevToolPlugin({
append: '\n',
filename: `${sourceMapsToken}/[file].map`,
})] : []),
],
}
};