diff --git a/.changeset/long-colts-listen.md b/.changeset/long-colts-listen.md new file mode 100644 index 00000000..ef73f33a --- /dev/null +++ b/.changeset/long-colts-listen.md @@ -0,0 +1,5 @@ +--- +'@ice/pkg': minor +--- + +feat: support `compileExcludes` options for transform diff --git a/packages/pkg/package.json b/packages/pkg/package.json index a8f9c03c..9464e409 100644 --- a/packages/pkg/package.json +++ b/packages/pkg/package.json @@ -59,6 +59,7 @@ "gzip-size": "^7.0.0", "lodash.merge": "^4.6.2", "magic-string": "^0.25.7", + "picomatch": "^2.3.1", "picocolors": "^1.0.0", "postcss": "^8.4.6", "postcss-plugin-rpx2vw": "^1.0.0", @@ -73,6 +74,7 @@ "@types/babel__core": "^7.1.20", "@types/fs-extra": "^9.0.13", "@types/lodash.merge": "^4.6.7", + "@types/picomatch": "^2.0.0", "@types/node": "^17.0.2", "cssnano": "^5.1.15", "jest": "^29.4.3", diff --git a/packages/pkg/src/tasks/transform.ts b/packages/pkg/src/tasks/transform.ts index f97ff418..5f6d1cf3 100644 --- a/packages/pkg/src/tasks/transform.ts +++ b/packages/pkg/src/tasks/transform.ts @@ -19,6 +19,7 @@ import type { } from '../types.js'; import type { RollupOptions, SourceMapInput } from 'rollup'; import { getTransformEntryDirs } from '../helpers/getTaskIO.js'; +import picomatch from 'picomatch'; export const watchTransformTasks: RunTasks = async (taskOptionsList, context, watcher) => { const handleChangeFunctions: HandleChange[] = []; @@ -128,6 +129,8 @@ async function runTransform( }, }); + const excludeMatcher = picomatch(userConfig?.transform?.compileExcludes ?? []); + const start = performance.now(); logger.debug('Transform start...'); @@ -150,7 +153,7 @@ async function runTransform( let map: SourceMapInput = null; // User should use plugins to transform other types of files. - if (loadResult === null && !INCLUDES_UTF8_FILE_TYPE.test(files[i].ext)) { + if (excludeMatcher(files[i].filePath) || (loadResult === null && !INCLUDES_UTF8_FILE_TYPE.test(files[i].ext))) { fs.copyFileSync(files[i].absolutePath, dest); logger.debug(`Transform file ${files[i].absolutePath}`, timeFrom(traverseFileStart)); diff --git a/packages/pkg/src/types.ts b/packages/pkg/src/types.ts index f125c322..7d992155 100644 --- a/packages/pkg/src/types.ts +++ b/packages/pkg/src/types.ts @@ -36,6 +36,10 @@ export interface TransformUserConfig { * @see https://github.com/isaacs/minimatch */ excludes?: string | string[]; + /** + * Exclude compiling files which are copy. + */ + compileExcludes?: string | string[]; } export interface BundleUserConfig { diff --git a/packages/pkg/tests/fixtures/transform-excludes/package.json b/packages/pkg/tests/fixtures/transform-excludes/package.json new file mode 100644 index 00000000..a6a2357f --- /dev/null +++ b/packages/pkg/tests/fixtures/transform-excludes/package.json @@ -0,0 +1,8 @@ +{ + "name": "@ice/pkg-tests-fixtures-transform-excludes", + "version": "0.0.0", + "private": true, + "dependencies": { + "@ice/pkg": "workspace:*" + } +} diff --git a/packages/pkg/tests/fixtures/transform-excludes/src/index.min.js b/packages/pkg/tests/fixtures/transform-excludes/src/index.min.js new file mode 100644 index 00000000..1b53228d --- /dev/null +++ b/packages/pkg/tests/fixtures/transform-excludes/src/index.min.js @@ -0,0 +1,3 @@ +'use strict'; +const path = require('path'); +console.log(path); diff --git a/packages/pkg/tests/fixtures/transform-excludes/src/index.ts b/packages/pkg/tests/fixtures/transform-excludes/src/index.ts new file mode 100644 index 00000000..96c0dbc9 --- /dev/null +++ b/packages/pkg/tests/fixtures/transform-excludes/src/index.ts @@ -0,0 +1 @@ +export const title = 'index' diff --git a/packages/pkg/tests/fixtures/transform-excludes/src/nested/n1.less b/packages/pkg/tests/fixtures/transform-excludes/src/nested/n1.less new file mode 100644 index 00000000..2d130df9 --- /dev/null +++ b/packages/pkg/tests/fixtures/transform-excludes/src/nested/n1.less @@ -0,0 +1 @@ +.foo { color: red; } diff --git a/packages/pkg/tests/fixtures/transform-excludes/src/nested/n1.min.js b/packages/pkg/tests/fixtures/transform-excludes/src/nested/n1.min.js new file mode 100644 index 00000000..1b53228d --- /dev/null +++ b/packages/pkg/tests/fixtures/transform-excludes/src/nested/n1.min.js @@ -0,0 +1,3 @@ +'use strict'; +const path = require('path'); +console.log(path); diff --git a/packages/pkg/tests/fixtures/transform-excludes/src/nested/n1.ts b/packages/pkg/tests/fixtures/transform-excludes/src/nested/n1.ts new file mode 100644 index 00000000..721490c7 --- /dev/null +++ b/packages/pkg/tests/fixtures/transform-excludes/src/nested/n1.ts @@ -0,0 +1 @@ +export const path = 'nested/n1' diff --git a/packages/pkg/tests/fixtures/transform-excludes/src/nested/n2.ts b/packages/pkg/tests/fixtures/transform-excludes/src/nested/n2.ts new file mode 100644 index 00000000..ab7fbeee --- /dev/null +++ b/packages/pkg/tests/fixtures/transform-excludes/src/nested/n2.ts @@ -0,0 +1 @@ +export const path = 'nested/n2' diff --git a/packages/pkg/tests/projects/__snapshots__/transform-excludes.test.ts.snap b/packages/pkg/tests/projects/__snapshots__/transform-excludes.test.ts.snap new file mode 100644 index 00000000..7b585604 --- /dev/null +++ b/packages/pkg/tests/projects/__snapshots__/transform-excludes.test.ts.snap @@ -0,0 +1,305 @@ +// Vitest Snapshot v1 + +exports[`Run config compile-excludes > cjs structure 1`] = ` +{ + "files": [ + { + "name": "index.js", + }, + { + "name": "index.min.js", + }, + { + "files": [ + { + "name": "n1.js", + }, + { + "name": "n1.less", + }, + { + "name": "n1.min.js", + }, + { + "name": "n2.js", + }, + ], + "name": "nested", + }, + ], + "name": "cjs", +} +`; + +exports[`Run config compile-excludes > dist structure 1`] = `null`; + +exports[`Run config compile-excludes > es2017 structure 1`] = ` +{ + "files": [ + { + "name": "index.js", + }, + { + "name": "index.min.js", + }, + { + "files": [ + { + "name": "n1.js", + }, + { + "name": "n1.less", + }, + { + "name": "n1.min.js", + }, + { + "name": "n2.js", + }, + ], + "name": "nested", + }, + ], + "name": "es2017", +} +`; + +exports[`Run config compile-excludes > esm structure 1`] = ` +{ + "files": [ + { + "name": "index.js", + }, + { + "name": "index.min.js", + }, + { + "files": [ + { + "name": "n1.js", + }, + { + "name": "n1.less", + }, + { + "name": "n1.min.js", + }, + { + "name": "n2.js", + }, + ], + "name": "nested", + }, + ], + "name": "esm", +} +`; + +exports[`Run config compile-excludes > file content cjs/index.js 1`] = ` +"\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { + value: true +}); +Object.defineProperty(exports, \\"title\\", { + enumerable: true, + get: function() { + return title; + } +}); +var title = \\"index\\"; +" +`; + +exports[`Run config compile-excludes > file content cjs/index.min.js 1`] = ` +"'use strict'; +const path = require('path'); +console.log(path); +" +`; + +exports[`Run config compile-excludes > file content cjs/nested/n1.js 1`] = ` +"\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { + value: true +}); +Object.defineProperty(exports, \\"path\\", { + enumerable: true, + get: function() { + return path; + } +}); +var path = \\"nested/n1\\"; +" +`; + +exports[`Run config compile-excludes > file content cjs/nested/n1.less 1`] = ` +".foo { color: red; } +" +`; + +exports[`Run config compile-excludes > file content cjs/nested/n1.min.js 1`] = ` +"'use strict'; +const path = require('path'); +console.log(path); +" +`; + +exports[`Run config compile-excludes > file content cjs/nested/n2.js 1`] = ` +"\\"use strict\\"; +Object.defineProperty(exports, \\"__esModule\\", { + value: true +}); +Object.defineProperty(exports, \\"path\\", { + enumerable: true, + get: function() { + return path; + } +}); +var path = \\"nested/n2\\"; +" +`; + +exports[`Run config compile-excludes > file content es2017/index.js 1`] = ` +"export const title = 'index'; +" +`; + +exports[`Run config compile-excludes > file content es2017/index.min.js 1`] = ` +"'use strict'; +const path = require('path'); +console.log(path); +" +`; + +exports[`Run config compile-excludes > file content es2017/nested/n1.js 1`] = ` +"export const path = 'nested/n1'; +" +`; + +exports[`Run config compile-excludes > file content es2017/nested/n1.less 1`] = ` +".foo { color: red; } +" +`; + +exports[`Run config compile-excludes > file content es2017/nested/n1.min.js 1`] = ` +"'use strict'; +const path = require('path'); +console.log(path); +" +`; + +exports[`Run config compile-excludes > file content es2017/nested/n2.js 1`] = ` +"export const path = 'nested/n2'; +" +`; + +exports[`Run config compile-excludes > file content esm/index.js 1`] = ` +"export var title = \\"index\\"; +" +`; + +exports[`Run config compile-excludes > file content esm/index.min.js 1`] = ` +"'use strict'; +const path = require('path'); +console.log(path); +" +`; + +exports[`Run config compile-excludes > file content esm/nested/n1.js 1`] = ` +"export var path = \\"nested/n1\\"; +" +`; + +exports[`Run config compile-excludes > file content esm/nested/n1.less 1`] = ` +".foo { color: red; } +" +`; + +exports[`Run config compile-excludes > file content esm/nested/n1.min.js 1`] = ` +"'use strict'; +const path = require('path'); +console.log(path); +" +`; + +exports[`Run config compile-excludes > file content esm/nested/n2.js 1`] = ` +"export var path = \\"nested/n2\\"; +" +`; + +exports[`Run config excludes > cjs structure 1`] = ` +{ + "files": [ + { + "name": "index.js", + }, + { + "name": "index.min.js", + }, + { + "files": [ + { + "name": "n1.less", + }, + { + "name": "n1.min.js", + }, + ], + "name": "nested", + }, + ], + "name": "cjs", +} +`; + +exports[`Run config excludes > dist structure 1`] = `null`; + +exports[`Run config excludes > es2017 structure 1`] = ` +{ + "files": [ + { + "name": "index.js", + }, + { + "name": "index.min.js", + }, + { + "files": [ + { + "name": "n1.less", + }, + { + "name": "n1.min.js", + }, + ], + "name": "nested", + }, + ], + "name": "es2017", +} +`; + +exports[`Run config excludes > esm structure 1`] = ` +{ + "files": [ + { + "name": "index.js", + }, + { + "name": "index.min.js", + }, + { + "files": [ + { + "name": "n1.less", + }, + { + "name": "n1.min.js", + }, + ], + "name": "nested", + }, + ], + "name": "esm", +} +`; diff --git a/packages/pkg/tests/projects/helper.ts b/packages/pkg/tests/projects/helper.ts index 97401e2c..c79917cb 100644 --- a/packages/pkg/tests/projects/helper.ts +++ b/packages/pkg/tests/projects/helper.ts @@ -3,13 +3,15 @@ import * as path from 'node:path' import * as url from "node:url"; import * as fse from 'fs-extra' import fs from "fs-extra"; -import { execSync, spawn } from 'node:child_process' -import { UserConfig } from '../../src' +import { execSync } from 'node:child_process' +import { UserConfig, TransformUserConfig } from '../../src' const fixturesDir = path.join(url.fileURLToPath(import.meta.url), '../../fixtures') const CHECK_DIRS = ['es2017', 'esm', 'dist', 'cjs'] +export const ALL_TRANSFORM_FORMATS: TransformUserConfig['formats'] = ['cjs', 'es2017', 'esm'] + export interface ProjectTestUserConfig { name: string, config?: string | UserConfig diff --git a/packages/pkg/tests/projects/transform-excludes.test.ts b/packages/pkg/tests/projects/transform-excludes.test.ts new file mode 100644 index 00000000..df349d35 --- /dev/null +++ b/packages/pkg/tests/projects/transform-excludes.test.ts @@ -0,0 +1,22 @@ +import { ALL_TRANSFORM_FORMATS, runProjectTest } from "./helper"; + +runProjectTest('transform-excludes', [{ + name: 'excludes', + snapshot: 'structure', + config: { + transform: { + formats: ALL_TRANSFORM_FORMATS, + excludes: ['**/n*.ts'], + }, + declaration: false + } +}, { + name: 'compile-excludes', + config: { + transform: { + formats: ALL_TRANSFORM_FORMATS, + compileExcludes: ['**/*.min.js'], + }, + declaration: false, + } +}]) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2b07d1fc..bac6be4b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -426,6 +426,9 @@ importers: picocolors: specifier: ^1.0.0 version: 1.0.0 + picomatch: + specifier: ^2.3.1 + version: 2.3.1 postcss: specifier: ^8.4.6 version: 8.4.14 @@ -463,6 +466,9 @@ importers: '@types/node': specifier: ^17.0.2 version: 17.0.45 + '@types/picomatch': + specifier: ^2.0.0 + version: 2.3.4 cssnano: specifier: ^5.1.15 version: 5.1.15(postcss@8.4.14) @@ -491,6 +497,12 @@ importers: specifier: workspace:* version: link:../../.. + packages/pkg/tests/fixtures/transform-excludes: + dependencies: + '@ice/pkg': + specifier: workspace:* + version: link:../../.. + packages/plugin-docusaurus: dependencies: '@docusaurus/core': @@ -7420,6 +7432,10 @@ packages: /@types/parse5@5.0.3: resolution: {integrity: sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==} + /@types/picomatch@2.3.4: + resolution: {integrity: sha512-0so8lU8O5zatZS/2Fi4zrwks+vZv7e0dygrgEZXljODXBig97l4cPQD+9LabXfGJOWwoRkTVz6Q4edZvD12UOA==} + dev: true + /@types/prettier@2.7.2: resolution: {integrity: sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==} dev: true diff --git a/website/docs/reference/config.md b/website/docs/reference/config.md index 41f0ad3a..349136ac 100644 --- a/website/docs/reference/config.md +++ b/website/docs/reference/config.md @@ -266,20 +266,43 @@ export default defineConfig({ + 类型:`string | string[]` + 默认值:`undefined` -排除无需编译的文件。比如,我们不想编译 `src` 下的所有测试文件,其中测试文件包含在 `__tests__` 目录下,或以 `*.test.[j|t]s` 结尾。 +排除无需处理的文件,既不会进行编译,也不会进行拷贝。 +比如,不想处理 `src` 下的所有测试文件,其中测试文件包含在 `__tests__` 目录下,或以 `*.test.[j|t]s` 结尾。 ```ts title="build.config.mts" import { defineConfig } from '@ice/pkg'; export default defineConfig({ transfrom: { - excludes: ['**/__tests__/**', '*.test.[j|t]s'], + excludes: ['**/__tests__/**', '**/*.test.[j|t]s'], }, }); ``` `excludes` 的配置完全遵循 [minimatch](https://github.com/isaacs/minimatch) 写法。 +#### compileExcludes + ++ 类型:`string | string[]` ++ 默认值: `undefined` ++ 可用版本: `1.6.0` + +排除无需编译但需要进行拷贝的代码文件。 + +例如,不希望重复编译 `.min.js` 后缀的文件,但是又希望能够直接拷贝到输出文件夹内,则可以按照如下配置 + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +export default defineConfig({ + transfrom: { + compileExcludes: ['**/*.min.js'], + }, +}); +``` + +配置规则和 `excludes` 一致。 + ### bundle 该字段定义 [Bundle 模式](../guide/abilities#双模式构建) 下额外的配置,若开启,默认生成 `dist` 文件目录。`bundle` 包含以下配置: