@codelet/cli-service 0.0.15 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/config.d.ts CHANGED
@@ -4,6 +4,8 @@ export interface Config {
4
4
  entryPath?: string;
5
5
  /** 入口文件 */
6
6
  source?: string[];
7
+ /** 不参与打包、运行时 require 的外部脚本 */
8
+ externalSource?: string[];
7
9
  /** 第一页 */
8
10
  pageIndex?: string;
9
11
  /** 静态文件 */
package/dist/config.js CHANGED
@@ -10,13 +10,15 @@ const inject_chunk_webpack_plugin_1 = __importDefault(require("@codelet/inject-c
10
10
  const mini_css_extract_plugin_1 = __importDefault(require("mini-css-extract-plugin"));
11
11
  const terser_webpack_plugin_1 = __importDefault(require("terser-webpack-plugin"));
12
12
  const copy_webpack_plugin_1 = __importDefault(require("copy-webpack-plugin"));
13
+ const path_1 = __importDefault(require("path"));
13
14
  const webpackbar_1 = __importDefault(require("webpackbar"));
14
15
  const utils_1 = require("./utils");
15
16
  function getDefaultConfig(options) {
16
- const { entryPath, source, pageIndex, publicDir, isDev } = Object.assign({
17
+ const { entryPath, source, externalSource, pageIndex, publicDir, isDev } = Object.assign({
17
18
  isDev: false,
18
19
  pageIndex: '',
19
20
  publicDir: 'public',
21
+ externalSource: [],
20
22
  entryPath: './src',
21
23
  source: [
22
24
  'app.(js|ts)',
@@ -24,6 +26,11 @@ function getDefaultConfig(options) {
24
26
  'packages/*/(pages|components)/**/index.(js|ts)',
25
27
  ],
26
28
  }, options);
29
+ const externalFiles = (0, utils_1.resolveExternalFiles)(entryPath, externalSource);
30
+ const resolveExternalFile = (0, utils_1.createExternalRequestResolver)({
31
+ entryPath,
32
+ externalFiles,
33
+ });
27
34
  // 模式
28
35
  const mode = isDev ? 'development' : 'production';
29
36
  // 插件
@@ -42,68 +49,20 @@ function getDefaultConfig(options) {
42
49
  to: './', // 复制到输出目录(dist)的根路径
43
50
  noErrorOnMissing: true, // 若 public 目录不存在时不报错
44
51
  },
52
+ ...(0, utils_1.createExternalCopyPatterns)(entryPath, externalSource),
45
53
  ],
46
54
  }),
47
55
  new webpackbar_1.default(),
48
56
  ];
57
+ if (externalSource.length > 0) {
58
+ plugins.push(new utils_1.RewriteExternalRequestPlugin());
59
+ }
49
60
  if (isDev) {
50
61
  plugins.push(new hmr_webpack_plugin_1.default());
51
62
  }
52
63
  // 优化
53
- const packageRootPattern = /[\\/]src[\\/]packages[\\/]([^\\/]+)[\\/]/;
54
- const getPackageBundleName = (name) => {
55
- const normalizedName = name.replace(/\\/g, '/');
56
- if (normalizedName.startsWith('packages/')) {
57
- const [, packageName] = normalizedName.split('/');
58
- if (packageName) {
59
- return `packages/${packageName}/bundle`;
60
- }
61
- }
62
- return null;
63
- };
64
- const getModuleResource = (module) => {
65
- if (!module || typeof module !== 'object') {
66
- return '';
67
- }
68
- return 'resource' in module && typeof module.resource === 'string' ? module.resource : '';
69
- };
70
- const optimization = {
71
- splitChunks: {
72
- chunks: 'all',
73
- minChunks: 2,
74
- minSize: 0,
75
- cacheGroups: {
76
- subpackage: {
77
- test(module) {
78
- return Boolean(getModuleResource(module).match(packageRootPattern));
79
- },
80
- name(module, chunks) {
81
- const match = getModuleResource(module).match(packageRootPattern);
82
- if (!match) {
83
- return 'bundle';
84
- }
85
- const packageBundleName = `packages/${match[1]}/bundle`;
86
- const bundleNames = new Set(chunks
87
- .map((chunk) => chunk.name)
88
- .filter((name) => typeof name === 'string' && Boolean(name))
89
- .map((name) => getPackageBundleName(name))
90
- .filter((name) => typeof name === 'string' && Boolean(name)));
91
- return bundleNames.size <= 1 && bundleNames.has(packageBundleName)
92
- ? packageBundleName
93
- : 'bundle';
94
- },
95
- priority: 10,
96
- minChunks: 2,
97
- chunks: 'all',
98
- },
99
- main: {
100
- name: 'bundle',
101
- minChunks: 2,
102
- chunks: 'all',
103
- },
104
- },
105
- },
106
- };
64
+ // splitChunks 的组装逻辑放到 utils 中,保持这里专注于默认配置拼装。
65
+ const optimization = (0, utils_1.createOptimization)();
107
66
  // 生产环境
108
67
  if (!isDev) {
109
68
  optimization.minimize = true;
@@ -123,10 +82,34 @@ function getDefaultConfig(options) {
123
82
  pageIndex,
124
83
  entryPath,
125
84
  source,
85
+ externalSource,
126
86
  publicDir,
127
87
  webpack: {
128
88
  mode,
129
89
  devtool: false,
90
+ ...(externalSource.length > 0
91
+ ? {
92
+ externalsType: 'commonjs',
93
+ externals: [
94
+ ({ context, request }, callback) => {
95
+ if (!context || !request) {
96
+ callback();
97
+ return;
98
+ }
99
+ const targetFile = resolveExternalFile(context, request);
100
+ if (!targetFile) {
101
+ callback();
102
+ return;
103
+ }
104
+ const targetRequest = path_1.default
105
+ .relative((0, utils_1.resolve)(entryPath), targetFile)
106
+ .replace(/\\/g, '/')
107
+ .replace(/\.js$/, '');
108
+ callback(null, `commonjs ${utils_1.externalRequestPlaceholderPrefix}${targetRequest}`);
109
+ },
110
+ ],
111
+ }
112
+ : {}),
130
113
  output: {
131
114
  filename: '[name].js',
132
115
  path: (0, utils_1.resolve)('dist'),
@@ -135,7 +118,7 @@ function getDefaultConfig(options) {
135
118
  },
136
119
  resolve: {
137
120
  alias: {
138
- '@': (0, utils_1.resolve)('src'),
121
+ '@': (0, utils_1.resolve)(entryPath),
139
122
  },
140
123
  extensions: ['.js', '.ts'],
141
124
  },
package/dist/utils.d.ts CHANGED
@@ -1,12 +1,26 @@
1
- import type { Configuration } from 'webpack';
1
+ import type { ObjectPattern } from 'copy-webpack-plugin';
2
+ import { type Compiler, type Configuration } from 'webpack';
2
3
  export declare const cmd: string;
4
+ export declare const externalRequestPlaceholderPrefix = "__CODELET_EXTERNAL__/";
3
5
  export declare const resolve: (...args: string[]) => string;
6
+ export declare const resolveEntryRoot: (entryPath: string) => string;
7
+ export declare const resolveSourceRoot: (entryPath: string) => string;
4
8
  export declare const parseDir: (entryPath: string, source: string[]) => {
5
9
  entry: Record<string, {
6
10
  import: string;
7
11
  runtime: string;
8
12
  }>;
9
13
  };
14
+ export declare const resolveExternalFiles: (entryPath: string, externalSource: string[]) => string[];
15
+ export declare const createExternalCopyPatterns: (entryPath: string, externalSource: string[]) => ObjectPattern[];
16
+ export declare const createExternalRequestResolver: (options: {
17
+ entryPath: string;
18
+ externalFiles: string[];
19
+ }) => (context: string, request: string) => string;
20
+ export declare class RewriteExternalRequestPlugin {
21
+ apply(compiler: Compiler): void;
22
+ }
23
+ export declare const createOptimization: () => NonNullable<Configuration["optimization"]>;
10
24
  export declare function getOptionValue(argv: string[], option: string): string | undefined;
11
25
  export declare function parseArgv(argv: string[]): {
12
26
  configPath: string;
package/dist/utils.js CHANGED
@@ -3,20 +3,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.parseDir = exports.resolve = exports.cmd = void 0;
6
+ exports.createOptimization = exports.RewriteExternalRequestPlugin = exports.createExternalRequestResolver = exports.createExternalCopyPatterns = exports.resolveExternalFiles = exports.parseDir = exports.resolveSourceRoot = exports.resolveEntryRoot = exports.resolve = exports.externalRequestPlaceholderPrefix = exports.cmd = void 0;
7
7
  exports.getOptionValue = getOptionValue;
8
8
  exports.parseArgv = parseArgv;
9
9
  exports.getConfig = getConfig;
10
10
  const fast_glob_1 = __importDefault(require("fast-glob"));
11
11
  const fs_1 = __importDefault(require("fs"));
12
12
  const path_1 = __importDefault(require("path"));
13
+ const webpack_1 = require("webpack");
13
14
  const webpack_merge_1 = __importDefault(require("webpack-merge"));
14
15
  const config_1 = require("./config");
15
16
  exports.cmd = process.cwd();
17
+ exports.externalRequestPlaceholderPrefix = '__CODELET_EXTERNAL__/';
16
18
  const resolve = (...args) => path_1.default.resolve(exports.cmd, ...args);
17
19
  exports.resolve = resolve;
20
+ const resolveEntryRoot = (entryPath) => (0, exports.resolve)(entryPath);
21
+ exports.resolveEntryRoot = resolveEntryRoot;
22
+ const resolveSourceRoot = (entryPath) => (0, exports.resolveEntryRoot)(entryPath);
23
+ exports.resolveSourceRoot = resolveSourceRoot;
18
24
  const parseDir = (entryPath, source) => {
19
- entryPath = (0, exports.resolve)(entryPath);
25
+ entryPath = (0, exports.resolveEntryRoot)(entryPath);
20
26
  const filepaths = fast_glob_1.default.sync(source.map((item) => (0, exports.resolve)(entryPath, item).replace(/\\/g, '/')));
21
27
  const entry = filepaths.reduce((res, filepath) => {
22
28
  const relPath = path_1.default.relative(entryPath, filepath);
@@ -30,6 +36,137 @@ const parseDir = (entryPath, source) => {
30
36
  return { entry };
31
37
  };
32
38
  exports.parseDir = parseDir;
39
+ const resolveExternalFiles = (entryPath, externalSource) => {
40
+ const entryRoot = (0, exports.resolveEntryRoot)(entryPath);
41
+ return fast_glob_1.default
42
+ .sync(externalSource.map((item) => path_1.default.join(entryRoot, item).replace(/\\/g, '/')))
43
+ .map((filepath) => path_1.default.resolve(filepath));
44
+ };
45
+ exports.resolveExternalFiles = resolveExternalFiles;
46
+ const createExternalCopyPatterns = (entryPath, externalSource) => {
47
+ const entryRoot = (0, exports.resolveEntryRoot)(entryPath);
48
+ return externalSource.map((pattern) => ({
49
+ context: entryRoot,
50
+ from: pattern,
51
+ to: '[path][name][ext]',
52
+ noErrorOnMissing: true,
53
+ }));
54
+ };
55
+ exports.createExternalCopyPatterns = createExternalCopyPatterns;
56
+ const createExternalRequestResolver = (options) => {
57
+ const entryRoot = (0, exports.resolveEntryRoot)(options.entryPath);
58
+ const externalFileSet = new Set(options.externalFiles);
59
+ return (context, request) => {
60
+ const candidates = [];
61
+ // 同时支持 "@/libs/foo" 这类别名引用和 "./libs/foo" 这类相对引用。
62
+ if (request.startsWith('@/')) {
63
+ candidates.push(path_1.default.join(entryRoot, request.slice(2)));
64
+ }
65
+ else if (request.startsWith('.')) {
66
+ candidates.push(path_1.default.resolve(context, request));
67
+ }
68
+ else {
69
+ return '';
70
+ }
71
+ for (const basePath of candidates) {
72
+ for (const ext of ['', '.js']) {
73
+ const candidate = ext ? `${basePath}${ext}` : basePath;
74
+ if (externalFileSet.has(path_1.default.resolve(candidate))) {
75
+ return path_1.default.resolve(candidate);
76
+ }
77
+ }
78
+ }
79
+ return '';
80
+ };
81
+ };
82
+ exports.createExternalRequestResolver = createExternalRequestResolver;
83
+ class RewriteExternalRequestPlugin {
84
+ apply(compiler) {
85
+ compiler.hooks.thisCompilation.tap('RewriteExternalRequestPlugin', (compilation) => {
86
+ compilation.hooks.processAssets.tap({
87
+ name: 'RewriteExternalRequestPlugin',
88
+ stage: webpack_1.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY,
89
+ }, (assets) => {
90
+ for (const assetName of Object.keys(assets)) {
91
+ if (!assetName.endsWith('.js')) {
92
+ continue;
93
+ }
94
+ const source = assets[assetName].source().toString();
95
+ if (!source.includes(exports.externalRequestPlaceholderPrefix)) {
96
+ continue;
97
+ }
98
+ // 基于最终产物文件的位置重新计算外部 require 路径,
99
+ // 这样像 bundle.js 这类公共 chunk 也能拿到正确的运行时相对路径。
100
+ const rewritten = source.replace(/__CODELET_EXTERNAL__\/([^"'`]+)/g, (_match, target) => {
101
+ return path_1.default
102
+ .relative(path_1.default.dirname(assetName), target)
103
+ .replace(/\\/g, '/')
104
+ .replace(/^(?!\.)/, './');
105
+ });
106
+ assets[assetName] = new webpack_1.sources.RawSource(rewritten);
107
+ }
108
+ });
109
+ });
110
+ }
111
+ }
112
+ exports.RewriteExternalRequestPlugin = RewriteExternalRequestPlugin;
113
+ const createOptimization = () => {
114
+ const packageRootPattern = /[\\/]src[\\/]packages[\\/]([^\\/]+)[\\/]/;
115
+ const getPackageBundleName = (name) => {
116
+ const normalizedName = name.replace(/\\/g, '/');
117
+ if (normalizedName.startsWith('packages/')) {
118
+ const [, packageName] = normalizedName.split('/');
119
+ if (packageName) {
120
+ return `packages/${packageName}/bundle`;
121
+ }
122
+ }
123
+ return null;
124
+ };
125
+ const getModuleResource = (module) => {
126
+ if (!module || typeof module !== 'object') {
127
+ return '';
128
+ }
129
+ return 'resource' in module && typeof module.resource === 'string' ? module.resource : '';
130
+ };
131
+ return {
132
+ splitChunks: {
133
+ chunks: 'all',
134
+ minChunks: 2,
135
+ minSize: 0,
136
+ cacheGroups: {
137
+ subpackage: {
138
+ test(module) {
139
+ return Boolean(getModuleResource(module).match(packageRootPattern));
140
+ },
141
+ name(module, chunks) {
142
+ const match = getModuleResource(module).match(packageRootPattern);
143
+ if (!match) {
144
+ return 'bundle';
145
+ }
146
+ const packageBundleName = `packages/${match[1]}/bundle`;
147
+ const bundleNames = new Set(chunks
148
+ .map((chunk) => chunk.name)
149
+ .filter((name) => typeof name === 'string' && Boolean(name))
150
+ .map((name) => getPackageBundleName(name))
151
+ .filter((name) => typeof name === 'string' && Boolean(name)));
152
+ return bundleNames.size <= 1 && bundleNames.has(packageBundleName)
153
+ ? packageBundleName
154
+ : 'bundle';
155
+ },
156
+ priority: 10,
157
+ minChunks: 2,
158
+ chunks: 'all',
159
+ },
160
+ main: {
161
+ name: 'bundle',
162
+ minChunks: 2,
163
+ chunks: 'all',
164
+ },
165
+ },
166
+ },
167
+ };
168
+ };
169
+ exports.createOptimization = createOptimization;
33
170
  function getOptionValue(argv, option) {
34
171
  const index = argv.findIndex((item) => item === option);
35
172
  if (index > -1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codelet/cli-service",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "description": "cli-service",
5
5
  "bin": {
6
6
  "codelet-cli-service": "./bin/codelet-cli-service.js"
@@ -41,10 +41,10 @@
41
41
  "webpack": "5.89.0",
42
42
  "webpack-merge": "^5.10.0",
43
43
  "webpackbar": "^6.0.0",
44
- "@codelet/inject-chunk-webpack-plugin": "^0.0.8",
45
- "@codelet/hmr-webpack-plugin": "^0.0.3",
46
44
  "@codelet/copy-loader": "^0.0.7",
47
45
  "@codelet/app-json-webpack-plugin": "^0.0.8",
46
+ "@codelet/hmr-webpack-plugin": "^0.0.3",
47
+ "@codelet/inject-chunk-webpack-plugin": "^0.0.8",
48
48
  "@codelet/wxml-loader": "^0.0.9"
49
49
  },
50
50
  "devDependencies": {