hw-weapp-compiler 1.0.20 → 1.0.22

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/build/dev.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const webpack = require('webpack');
2
+ const chalk = require('chalk');
2
3
  const { ENV } = require('./config/constants');
3
4
  const webpackConfig = require('./webpack.config');
4
5
  const { createCompilerHandler } = require('./utils/createCompilerHandler');
@@ -20,7 +21,7 @@ module.exports = async (opts) => {
20
21
  ),
21
22
  );
22
23
 
23
- compiler.watch(
24
+ const watching = compiler.watch(
24
25
  {
25
26
  aggregateTimeout: 300,
26
27
  poll: false,
@@ -28,4 +29,9 @@ module.exports = async (opts) => {
28
29
  },
29
30
  createCompilerHandler('dev'),
30
31
  );
32
+
33
+ if (!opts || opts.quiet !== true) {
34
+ console.log(chalk.cyan('dev 正在监听文件变化'));
35
+ }
36
+ return watching;
31
37
  };
@@ -34,12 +34,14 @@ module.exports = async function loader(source) {
34
34
  return src ? [attr, src] : null;
35
35
  }),
36
36
  );
37
- for (let index = 0; index < assetResults.length; index += 1) {
38
- const result = assetResults[index];
39
- if (result) {
40
- const [attr, src] = result;
41
- content = content.split(attr).join(withPublicPath(src));
42
- }
37
+ // 路径可能互为后缀(如 a.png icons/a.png),必须先替换较长路径,
38
+ // 否则短路径会破坏尚未处理的长路径。
39
+ const resolvedAssets = assetResults
40
+ .filter(Boolean)
41
+ .sort(([left], [right]) => right.length - left.length);
42
+ for (let index = 0; index < resolvedAssets.length; index += 1) {
43
+ const [attr, src] = resolvedAssets[index];
44
+ content = content.split(attr).join(withPublicPath(src));
43
45
  }
44
46
 
45
47
  // wxml文件 - 并行 loadModule
@@ -116,13 +116,13 @@ function injectGlobalModules(content, assetName, flags) {
116
116
  'Function("r", "regeneratorRuntime = r")(runtime);',
117
117
  'global.regeneratorRuntime = runtime',
118
118
  );
119
- if (!/require('\.\/commons\.js')/.test(result) && flags.hasCommonJs) {
119
+ if (!result.includes("require('./commons.js');") && flags.hasCommonJs) {
120
120
  result = `require('./commons.js');\n${result}`;
121
121
  }
122
- if (!/require('\.\/vendors\.js')/.test(result) && flags.hasVendorJs) {
122
+ if (!result.includes("require('./vendors.js');") && flags.hasVendorJs) {
123
123
  result = `require('./vendors.js');\n${result}`;
124
124
  }
125
- if (!/require('\.\/runtime\.js')/.test(result) && flags.hasRuntimeJs) {
125
+ if (!result.includes("require('./runtime.js');") && flags.hasRuntimeJs) {
126
126
  result = `require('./runtime.js');\n${result}`;
127
127
  }
128
128
  }
package/build/prod.js CHANGED
@@ -16,7 +16,7 @@ module.exports = async (opts) => {
16
16
  devtool: false,
17
17
  output: {
18
18
  clean: {
19
- keep: /^(project\.config\.json|weapp\.env\.json)$/,
19
+ keep: /^weapp\.env\.json$/,
20
20
  },
21
21
  },
22
22
  optimization: {
@@ -2,7 +2,7 @@ const path = require('path');
2
2
  const fse = require('fs-extra');
3
3
  const { DIST_DIR } = require('../config/constants');
4
4
 
5
- const KEEP_FILES = new Set(['project.config.json', 'weapp.env.json']);
5
+ const KEEP_FILES = new Set(['weapp.env.json']);
6
6
 
7
7
  /**
8
8
  * 开发模式启动时清理 dist 旧产物。
@@ -69,7 +69,9 @@ function getWxmlAssets(filePath, content) {
69
69
  const filteredAttrs = allAttrs
70
70
  .filter((item) => !!item)
71
71
  .map((item) => item.split('?')[0])
72
- .filter((item) => !/^(?:https?:)?\/\//i.test(item))
72
+ // http(s)、cloud、wxfile、data 等带协议资源均由小程序运行时处理,
73
+ // 只有本地相对路径、根路径和 webpack alias 才进入 resolver。
74
+ .filter((item) => !/^(?:[a-z][a-z\d+.-]*:|\/\/)/i.test(item))
73
75
  .filter((item) => !/{{.*}}/.test(item))
74
76
  .filter((item) => !/\+.*\+/.test(item));
75
77
 
@@ -4,18 +4,40 @@ const { debounce } = require('throttle-debounce');
4
4
 
5
5
  const tempDir = path.resolve(process.cwd(), '.temp');
6
6
  const uploadJsonDir = path.join(tempDir, 'upload.json');
7
+ const uploadJsonTempDir = `${uploadJsonDir}.${process.pid}.tmp`;
7
8
  let uploadJson = {};
8
- const writeUploadJsonDebounce = debounce(300, () => {
9
- fs.writeJSONSync(uploadJsonDir, uploadJson);
10
- });
11
9
 
12
- if (!fs.existsSync(tempDir)) {
13
- fs.mkdirSync(tempDir);
10
+ function writeUploadJson() {
11
+ try {
12
+ fs.writeJSONSync(uploadJsonTempDir, uploadJson);
13
+ fs.renameSync(uploadJsonTempDir, uploadJsonDir);
14
+ } catch (error) {
15
+ try {
16
+ fs.removeSync(uploadJsonTempDir);
17
+ } catch (cleanupError) {
18
+ console.warn('清理上传缓存临时文件失败:', cleanupError);
19
+ }
20
+ console.warn('写入上传缓存失败,本次构建将继续:', error);
21
+ }
14
22
  }
23
+
24
+ const writeUploadJsonDebounce = debounce(300, writeUploadJson);
25
+
26
+ fs.ensureDirSync(tempDir);
15
27
  if (!fs.existsSync(uploadJsonDir)) {
16
- fs.writeJSONSync(uploadJsonDir, uploadJson);
28
+ writeUploadJson();
17
29
  } else {
18
- uploadJson = fs.readJSONSync(uploadJsonDir);
30
+ try {
31
+ const stored = fs.readJSONSync(uploadJsonDir);
32
+ if (!stored || Array.isArray(stored) || typeof stored !== 'object') {
33
+ throw new TypeError('上传缓存必须是 JSON 对象');
34
+ }
35
+ uploadJson = stored;
36
+ } catch (error) {
37
+ console.warn('上传缓存已损坏,将重建缓存:', error);
38
+ uploadJson = {};
39
+ writeUploadJson();
40
+ }
19
41
  }
20
42
 
21
43
  module.exports = {
@@ -16,7 +16,7 @@ const { DIST_DIR } = require('../config/constants');
16
16
 
17
17
  const { obsConfig, ossConfig } = getConfig();
18
18
 
19
- let obsClient;
19
+ let obsClientPromise;
20
20
  let ossClient;
21
21
 
22
22
  function getObsResponseError(action, result) {
@@ -60,13 +60,26 @@ function createObsCallback(action, resolve, reject) {
60
60
  };
61
61
  }
62
62
 
63
+ async function initializeObsClient(Client = OBSClient, config = obsConfig) {
64
+ const client = new Client({ ...config });
65
+
66
+ // esdk-obs-nodejs 3.26.x 的构造函数不会等待异步 initFactory()。
67
+ // 静态 AK/SK 初始化会在下一个微任务完成,立即调用 API 时 signatureContext 仍为 null。
68
+ await Promise.resolve();
69
+ if (!client.util || !client.util.signatureContext) {
70
+ throw new Error('OBS client initialization failed');
71
+ }
72
+ return client;
73
+ }
74
+
63
75
  function getObsClient() {
64
- if (!obsClient) {
65
- obsClient = new OBSClient({
66
- ...obsConfig,
76
+ if (!obsClientPromise) {
77
+ obsClientPromise = initializeObsClient().catch((error) => {
78
+ obsClientPromise = undefined;
79
+ throw error;
67
80
  });
68
81
  }
69
- return obsClient;
82
+ return obsClientPromise;
70
83
  }
71
84
 
72
85
  function getOssClient() {
@@ -89,9 +102,10 @@ function getOssStat(file) {
89
102
  return getOssClient().head(compatiblePath(path.join(ossConfig.dir, path.relative(DIST_DIR, file))));
90
103
  }
91
104
 
92
- function doObsUpload(file) {
105
+ async function doObsUpload(file) {
106
+ const client = await getObsClient();
93
107
  return new Promise((resolve, reject) => {
94
- getObsClient().putObject(
108
+ client.putObject(
95
109
  {
96
110
  Bucket: obsConfig.bucket,
97
111
  Key: compatiblePath(path.join(obsConfig.dir, path.relative(DIST_DIR, file))),
@@ -102,8 +116,9 @@ function doObsUpload(file) {
102
116
  });
103
117
  }
104
118
  async function getObsStat(file) {
119
+ const client = await getObsClient();
105
120
  return new Promise((resolve, reject) => {
106
- getObsClient().getObjectMetadata(
121
+ client.getObjectMetadata(
107
122
  {
108
123
  Bucket: obsConfig.bucket,
109
124
  Key: compatiblePath(path.join(obsConfig.dir, path.relative(DIST_DIR, file))),
@@ -189,6 +204,7 @@ module.exports = {
189
204
  _internals: {
190
205
  createObsCallback,
191
206
  getObsResponseError,
207
+ initializeObsClient,
192
208
  uploadFile,
193
209
  uploadFiles,
194
210
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hw-weapp-compiler",
3
- "version": "1.0.20",
3
+ "version": "1.0.22",
4
4
  "description": "基于 webpack5 的小程序构建工具,兼容 Node.js 18~24",
5
5
  "main": "index.js",
6
6
  "bin": {