@codelet/cli-service 0.0.14 → 0.0.16

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,16 +10,27 @@ 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
- source: ['app.(js|ts)', 'pages/**/*.(js|ts)', 'components/**/*.(js|ts)'],
23
+ source: [
24
+ 'app.(js|ts)',
25
+ '(pages|components)/**/index.(js|ts)',
26
+ 'packages/*/(pages|components)/**/index.(js|ts)',
27
+ ],
22
28
  }, options);
29
+ const externalFiles = (0, utils_1.resolveExternalFiles)(entryPath, externalSource);
30
+ const resolveExternalFile = (0, utils_1.createExternalRequestResolver)({
31
+ entryPath,
32
+ externalFiles,
33
+ });
23
34
  // 模式
24
35
  const mode = isDev ? 'development' : 'production';
25
36
  // 插件
@@ -38,68 +49,20 @@ function getDefaultConfig(options) {
38
49
  to: './', // 复制到输出目录(dist)的根路径
39
50
  noErrorOnMissing: true, // 若 public 目录不存在时不报错
40
51
  },
52
+ ...(0, utils_1.createExternalCopyPatterns)(entryPath, externalSource),
41
53
  ],
42
54
  }),
43
55
  new webpackbar_1.default(),
44
56
  ];
57
+ if (externalSource.length > 0) {
58
+ plugins.push(new utils_1.RewriteExternalRequestPlugin());
59
+ }
45
60
  if (isDev) {
46
61
  plugins.push(new hmr_webpack_plugin_1.default());
47
62
  }
48
63
  // 优化
49
- const packageRootPattern = /[\\/]src[\\/]packages[\\/]([^\\/]+)[\\/]/;
50
- const getPackageBundleName = (name) => {
51
- const normalizedName = name.replace(/\\/g, '/');
52
- if (normalizedName.startsWith('packages/')) {
53
- const [, packageName] = normalizedName.split('/');
54
- if (packageName) {
55
- return `packages/${packageName}/bundle`;
56
- }
57
- }
58
- return null;
59
- };
60
- const getModuleResource = (module) => {
61
- if (!module || typeof module !== 'object') {
62
- return '';
63
- }
64
- return 'resource' in module && typeof module.resource === 'string' ? module.resource : '';
65
- };
66
- const optimization = {
67
- splitChunks: {
68
- chunks: 'all',
69
- minChunks: 2,
70
- minSize: 0,
71
- cacheGroups: {
72
- subpackage: {
73
- test(module) {
74
- return Boolean(getModuleResource(module).match(packageRootPattern));
75
- },
76
- name(module, chunks) {
77
- const match = getModuleResource(module).match(packageRootPattern);
78
- if (!match) {
79
- return 'bundle';
80
- }
81
- const packageBundleName = `packages/${match[1]}/bundle`;
82
- const bundleNames = new Set(chunks
83
- .map((chunk) => chunk.name)
84
- .filter((name) => typeof name === 'string' && Boolean(name))
85
- .map((name) => getPackageBundleName(name))
86
- .filter((name) => typeof name === 'string' && Boolean(name)));
87
- return bundleNames.size <= 1 && bundleNames.has(packageBundleName)
88
- ? packageBundleName
89
- : 'bundle';
90
- },
91
- priority: 10,
92
- minChunks: 2,
93
- chunks: 'all',
94
- },
95
- main: {
96
- name: 'bundle',
97
- minChunks: 2,
98
- chunks: 'all',
99
- },
100
- },
101
- },
102
- };
64
+ // splitChunks 的组装逻辑放到 utils 中,保持这里专注于默认配置拼装。
65
+ const optimization = (0, utils_1.createOptimization)();
103
66
  // 生产环境
104
67
  if (!isDev) {
105
68
  optimization.minimize = true;
@@ -119,10 +82,30 @@ function getDefaultConfig(options) {
119
82
  pageIndex,
120
83
  entryPath,
121
84
  source,
85
+ externalSource,
122
86
  publicDir,
123
87
  webpack: {
124
88
  mode,
125
89
  devtool: false,
90
+ externalsType: 'commonjs',
91
+ externals: [
92
+ ({ context, request }, callback) => {
93
+ if (!context || !request) {
94
+ callback();
95
+ return;
96
+ }
97
+ const targetFile = resolveExternalFile(context, request);
98
+ if (!targetFile) {
99
+ callback();
100
+ return;
101
+ }
102
+ const targetRequest = path_1.default
103
+ .relative((0, utils_1.resolve)(entryPath), targetFile)
104
+ .replace(/\\/g, '/')
105
+ .replace(/\.js$/, '');
106
+ callback(null, `commonjs ${utils_1.externalRequestPlaceholderPrefix}${targetRequest}`);
107
+ },
108
+ ],
126
109
  output: {
127
110
  filename: '[name].js',
128
111
  path: (0, utils_1.resolve)('dist'),
@@ -131,7 +114,7 @@ function getDefaultConfig(options) {
131
114
  },
132
115
  resolve: {
133
116
  alias: {
134
- '@': (0, utils_1.resolve)('src'),
117
+ '@': (0, utils_1.resolve)(entryPath),
135
118
  },
136
119
  extensions: ['.js', '.ts'],
137
120
  },
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.14",
3
+ "version": "0.0.16",
4
4
  "description": "cli-service",
5
5
  "bin": {
6
6
  "codelet-cli-service": "./bin/codelet-cli-service.js"
@@ -42,9 +42,9 @@
42
42
  "webpack-merge": "^5.10.0",
43
43
  "webpackbar": "^6.0.0",
44
44
  "@codelet/app-json-webpack-plugin": "^0.0.8",
45
+ "@codelet/copy-loader": "^0.0.7",
45
46
  "@codelet/hmr-webpack-plugin": "^0.0.3",
46
47
  "@codelet/inject-chunk-webpack-plugin": "^0.0.8",
47
- "@codelet/copy-loader": "^0.0.7",
48
48
  "@codelet/wxml-loader": "^0.0.9"
49
49
  },
50
50
  "devDependencies": {