import { babel } from "@rollup/plugin-babel"; import commonjs from "@rollup/plugin-commonjs"; import json from "@rollup/plugin-json"; import resolve from "@rollup/plugin-node-resolve"; import terser from "@rollup/plugin-terser"; import ts from "@rollup/plugin-typescript"; import type { RollupOptions, OutputOptions, InputOption, Plugin, } from "rollup"; import copy from "rollup-plugin-copy"; import del from "rollup-plugin-delete"; import path from "path"; import { fileURLToPath } from "url"; import pkg from "../../package.json" with { type: "json" }; import { PostCSSBundlePlugin, DisableTreeShakingPlugin, RemoveCssImportsPlugin, CopyrightCSSPlugin, NormalizeDeclarationImportsPlugin, } from "../lib/plugins/index"; // Текущая директория const __dirname = fileURLToPath(new URL(".", import.meta.url)); // Директория, куда собирается библиотека const dist = "dist/"; // Расширения JS const extensions = [ ".js", ".cjs", ".jsx", ".ts", ".tsx" ]; // Список пакетов const regexesOfPackages = [ pkg.name, ...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {}), ] // eslint-disable-next-line security/detect-non-literal-regexp .map((packageName) => new RegExp(`^${packageName}(/.*)?`)); // Глобальный API const globals = { "react": "React", "react-dom": "ReactDOM", }; // Выключенные по умолчанию плагины const excludedPlugins = [ "css-bundle", "css-chunks" ]; // tsconfig const tsconfig = path.resolve(__dirname, "./tsconfig.json"); // Входные точки const inputData: { input: InputOption; output?: OutputOptions; excludedPlugins?: string[]; }[] = [ { input: path.resolve("src/package/components/index.ts"), excludedPlugins: [ "css-bundle" ], }, { input: path.resolve("src/package/index.ts"), excludedPlugins: [ "css-chunks" ], }, { input: path.resolve("src/package/utils/webpack/index.ts"), excludedPlugins, }, { input: path.resolve("src/package/utils/node/index.ts"), excludedPlugins, }, { input: path.resolve("src/package/utils/react/index.ts"), excludedPlugins, }, { input: path.resolve("src/package/utils/msw/index.ts"), excludedPlugins, }, { input: path.resolve("src/package/utils/index.ts"), excludedPlugins, }, ]; // Задействованные плагины const plugins: Plugin[] = [ del({ runOnce: true, targets: `${dist}/*`, }), json(), resolve({ extensions, browser: true, preferBuiltins: true, resolveOnly: regexesOfPackages, }), commonjs({ transformMixedEsModules: true, esmExternals: true, }), // StripTypeJsDocPlugin(), ts({ include: [ path.resolve(".d.ts"), ...inputData.map(({ input }) => input as string) ], tsconfig, noEmitOnError: false, compilerOptions: { declaration: true, declarationDir: dist, jsx: "preserve", }, }), RemoveCssImportsPlugin(), copy({ verbose: false, flatten: true, copySync: true, targets: [ { // существующие src/package/**/*.d.ts => dist/**/*.d.mts src: "src/package/**/*.d.ts", dest: "dist", rename: (name, extension, fullPath) => { return fullPath.replaceAll("src\/package\/", ""); }, transform: (contents) => contents.toString().replaceAll(".d.ts", ".d.mts"), }, ], }), copy({ verbose: false, flatten: false, copySync: true, targets: [ { // генерируемые dist/**/*.d.ts => dist/**/*.d.mts src: "dist/**/*.d.ts", dest: "dist", rename: (name) => `${name}.mts`, transform: (contents) => contents.toString().replaceAll(".d.ts", ".d.mts"), }, ], }), babel({ inputSourceMap: false, targets: pkg.browserslist.production, minified: false, babelrc: false, configFile: false, babelHelpers: "runtime", exclude: [ "node_modules/**" ], presets: [ "@babel/preset-typescript", "@babel/preset-env", ], overrides: [ { test: /\.tsx$/, presets: [ [ "@babel/preset-react", { runtime: "automatic", development: false, }, ], ], }, ], plugins: [ "@babel/plugin-transform-runtime" ], extensions, }), ...await PostCSSBundlePlugin({ extract: "styles/legacy/index.css", }), ...await PostCSSBundlePlugin({ extract: "styles/legacy/components/{parent}/index.css", include: /components\/.*\/style.pcss$/, base: __dirname, }), CopyrightCSSPlugin(`Copyright (c) ${new Date().getFullYear()} Digital Element`), DisableTreeShakingPlugin({ patterns: [ "constants", "sanitizedHTMLConfig" ], }), terser({ mangle: false, compress: { dead_code: false, collapse_vars: false, arrows: false, defaults: false, ecma: 2020, evaluate: false, keep_classnames: true, keep_fnames: true, keep_fargs: true, keep_infinity: true, reduce_funcs: false, hoist_funs: false, join_vars: false, hoist_props: false, hoist_vars: false, }, format: { comments: "all", keep_numbers: true, }, }), NormalizeDeclarationImportsPlugin({ builds: inputData.length, directory: path.resolve(dist), }), ]; // Выходные данные const outputData: { plugins?: Plugin[]; input?: InputOption; output?: OutputOptions[]; }[] = inputData .map(({ input, output = {}, excludedPlugins = [], }) => { const activePlugins = excludedPlugins.length ? plugins.filter(({ name }) => { return !excludedPlugins.includes(name); }) : plugins; return { plugins: activePlugins, output: [ { ...output, }, ], input, }; }); /** * Получает конфигурацию * @param command{String=} * @returns {Promise} */ export default async function getConfig( command: Record ): Promise { return outputData.map(({ input = "", output = [], plugins = [], }) => { const outputData: OutputOptions[] = output.map((item) => { return { dir: dist, globals, esModule: true, preserveModules: true, preserveModulesRoot: "src/package", strict: false, sourcemap: true, sourcemapPathTransform: () => "", entryFileNames: "[name].mjs", chunkFileNames: "[name].[hash].mjs", format: "es", exports: "named", ...item, }; }); return { cache: false, input, treeshake: { moduleSideEffects: true, propertyReadSideEffects: "always", unknownGlobalSideEffects: true, }, output: outputData, plugins, external: regexesOfPackages, }; }); }