@playcraft/devkit 1.0.1-8.beta.1 → 1.0.1-8.beta.3
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/README.md +259 -0
- package/cli/bin/playable-scripts.js +44 -1
- package/cli/commands/build.js +130 -18
- package/cli/commands/builds.js +13 -2
- package/cli/commands/dev.js +7 -1
- package/cli/commands/pack.js +308 -39
- package/cli/commands/vite-dev.js +7 -1
- package/core/batch-build.js +1091 -125
- package/core/cos-uploader.js +264 -20
- package/core/index.js +71 -6
- package/core/loaders/gltf-loader.js +74 -28
- package/core/options.js +310 -15
- package/core/plugins/AdikteevInjectorPlugin.js +26 -4
- package/core/plugins/BigoAdsInjectorPlugin.js +21 -4
- package/core/plugins/DAPIInjectorPlugin.js +25 -2
- package/core/plugins/DebuggerInjectionPlugin.js +31 -3
- package/core/plugins/ExitAPIInjectorPlugin.js +57 -3
- package/core/plugins/FflateCompressionPlugin.js +225 -37
- package/core/plugins/FontInjectionWebpackPlugin.js +46 -4
- package/core/plugins/LiftoffInjectorPlugin.js +26 -4
- package/core/plugins/MRAIDInjectorPlugin.js +24 -2
- package/core/plugins/MintegralInjectorPlugin.js +25 -2
- package/core/plugins/PangleInjectorPlugin.js +24 -2
- package/core/plugins/SnapchatInjectorPlugin.js +26 -4
- package/core/plugins/TikTokInjectorPlugin.js +24 -2
- package/core/plugins/UnityInjectorPlugin.js +37 -8
- package/core/plugins/ZipPlugin.js +138 -19
- package/core/resources/fonts/maoken-regular.woff2 +0 -0
- package/core/resources/fonts/maoken-regular.woff2.chars +1 -0
- package/core/resources/fonts/maoken-zhuyuan.ttf +0 -0
- package/core/resources/fonts/pangmen-biaoti.ttf +0 -0
- package/core/resources/fonts/pangmen-regular.woff2 +0 -0
- package/core/resources/fonts/pangmen-regular.woff2.chars +1 -0
- package/core/utils/buildDefines.js +29 -2
- package/core/utils/buildTemplateString.js +40 -5
- package/core/utils/date.js +16 -1
- package/core/utils/fontRegistry.js +81 -12
- package/core/utils/fontResolver.js +335 -34
- package/core/utils/generateAdikteevHtmlWebpackPluginConfig.js +42 -7
- package/core/utils/generateBigabidHtmlWebpackPluginConfig.js +30 -3
- package/core/utils/generateInMobiHtmlWebpackPluginConfig.js +43 -7
- package/core/utils/injectSDKPlugins.js +58 -11
- package/core/utils/logOptions.js +37 -4
- package/core/utils/mergeOptions.js +19 -2
- package/core/utils/parseArgvOptions.js +110 -5
- package/core/utils/resolveChannelFold2Zip.js +15 -3
- package/core/utils/validateThemeData.js +220 -25
- package/core/validators/pre-build-checker.js +201 -21
- package/core/validators/tracking-validator.js +358 -40
- package/core/vite.dev.js +332 -18
- package/core/webpack.build.js +489 -56
- package/core/webpack.common.js +177 -11
- package/core/webpack.dev.js +82 -5
- package/package.json +3 -2
- package/core/resources/fonts/maoken/04e60956bbe055746aa7bca5c229ca8c.woff2 +0 -0
- package/core/resources/fonts/maoken/086a30eeaa0f5558062389361dca8685.woff2 +0 -0
- package/core/resources/fonts/maoken/1b1c9545aa1da01979d240f38f979b9e.woff2 +0 -0
- package/core/resources/fonts/maoken/1dd31fae60d98fcad0812cb4dc54afdd.woff2 +0 -0
- package/core/resources/fonts/maoken/1f08966635ca0dc4a64f519863df0dcc.woff2 +0 -0
- package/core/resources/fonts/maoken/26aab6a388b04c37fd5a4d066a512e14.woff2 +0 -0
- package/core/resources/fonts/maoken/29390db71394eb0d298fa1c339590e45.woff2 +0 -0
- package/core/resources/fonts/maoken/2b743d9f736c5cda9250fc8b85f69db8.woff2 +0 -0
- package/core/resources/fonts/maoken/2f16b1f8881909c4e65404610460797f.woff2 +0 -0
- package/core/resources/fonts/maoken/339dc88f6fd1b09336410154252f858f.woff2 +0 -0
- package/core/resources/fonts/maoken/3665591d2bd9a3f31a302a34a76c74dc.woff2 +0 -0
- package/core/resources/fonts/maoken/3b58ece5ff16a5addc9adc1c74717d12.woff2 +0 -0
- package/core/resources/fonts/maoken/3e3aacd6cd2255be39c97c4ed6eb978b.woff2 +0 -0
- package/core/resources/fonts/maoken/3e8cdd750fcbbfcf9a1101c7418eeb36.woff2 +0 -0
- package/core/resources/fonts/maoken/3f71b3c0ecb555f9fa88d1b2ae0ec77f.woff2 +0 -0
- package/core/resources/fonts/maoken/40f956d892d89a442992737448f0330b.woff2 +0 -0
- package/core/resources/fonts/maoken/47ecbb41501b6cb923aaa8b8324bb22f.woff2 +0 -0
- package/core/resources/fonts/maoken/4a6e704952e05d217e4f4d2c2a330094.woff2 +0 -0
- package/core/resources/fonts/maoken/4ec9fc653a6aaabd2296fac3fe906416.woff2 +0 -0
- package/core/resources/fonts/maoken/5d950afcbaac4bb8f44083e5f4572957.woff2 +0 -0
- package/core/resources/fonts/maoken/6505b718e31b5b2b29c4f50a2a2b5fe6.woff2 +0 -0
- package/core/resources/fonts/maoken/673405ebfdfebae1104f36efa778714d.woff2 +0 -0
- package/core/resources/fonts/maoken/695a686e27152d8e81b4459b64d7b6a1.woff2 +0 -0
- package/core/resources/fonts/maoken/6b5fb0c960eed7a53f39adb18d0ab28b.woff2 +0 -0
- package/core/resources/fonts/maoken/6f53ca6c761ff540e11d5f7111dad67c.woff2 +0 -0
- package/core/resources/fonts/maoken/7125e9df28437d053e56f85a908a7343.woff2 +0 -0
- package/core/resources/fonts/maoken/731865983ae51e2a4bdc6c194da0b82e.woff2 +0 -0
- package/core/resources/fonts/maoken/74d993e9aa68ef636eb1287439d06bb0.woff2 +0 -0
- package/core/resources/fonts/maoken/797653f0a72360cd584f625972b5d217.woff2 +0 -0
- package/core/resources/fonts/maoken/7af5930fe5e6dade3cf31d3287d6414c.woff2 +0 -0
- package/core/resources/fonts/maoken/7c6fe2ee55f924f00b097da208852a34.woff2 +0 -0
- package/core/resources/fonts/maoken/8cff8ef36a011ca7e6d103f29b22f98b.woff2 +0 -0
- package/core/resources/fonts/maoken/8ff8566257c5df17ddde67b2b48243a4.woff2 +0 -0
- package/core/resources/fonts/maoken/93988344f6df526a0033a05d2d927d76.woff2 +0 -0
- package/core/resources/fonts/maoken/99d1c5647f1ce540674bd32354c2038f.woff2 +0 -0
- package/core/resources/fonts/maoken/a328b132aac2a3f53d97b8e7ad940e1a.woff2 +0 -0
- package/core/resources/fonts/maoken/a7dc00c95dd1e7a8eca8053975b0c07c.woff2 +0 -0
- package/core/resources/fonts/maoken/ab93ca86fb3e7ad8e95b93f7de5d8f97.woff2 +0 -0
- package/core/resources/fonts/maoken/b1b83e931f7e2187786b87545a6ee842.woff2 +0 -0
- package/core/resources/fonts/maoken/bb31b8c0ccf2d93af7cc25f19a576970.woff2 +0 -0
- package/core/resources/fonts/maoken/bd4a61534e4a0f426dd0d396362b211d.woff2 +0 -0
- package/core/resources/fonts/maoken/bec7534be141c6473023f18f5aee7a0e.woff2 +0 -0
- package/core/resources/fonts/maoken/c133a76c68c645b46b20e7faf9894ab6.woff2 +0 -0
- package/core/resources/fonts/maoken/c2deab25bd23b63c794da537e208c61a.woff2 +0 -0
- package/core/resources/fonts/maoken/cf13611d9749dd23fd9737073d2110f6.woff2 +0 -0
- package/core/resources/fonts/maoken/d01182e5dd9f51dce713916e8f872bbf.woff2 +0 -0
- package/core/resources/fonts/maoken/d1d4c88b2a14e679d3cc9d0ad8e8abdb.woff2 +0 -0
- package/core/resources/fonts/maoken/df61c7f5fa45aa6156122c09653f6700.woff2 +0 -0
- package/core/resources/fonts/maoken/e1867d1454d8c903ba29bac70f88c211.woff2 +0 -0
- package/core/resources/fonts/maoken/ef912f41f9109c5d936005af5552f521.woff2 +0 -0
- package/core/resources/fonts/maoken/f0f119744871bb6bec7e0eef4e1ce8ba.woff2 +0 -0
- package/core/resources/fonts/maoken/f32a268245b50f6c19bd946239fd8cc0.woff2 +0 -0
- package/core/resources/fonts/maoken/f4735851e08da122f471100ecff5c4ae.woff2 +0 -0
- package/core/resources/fonts/maoken/f85b8f6994600622f767506ae55d6280.woff2 +0 -0
- package/core/resources/fonts/maoken/fc145bdf9c20b67db44156382155b465.woff2 +0 -0
- package/core/resources/fonts/maoken/fcd8571ec88b953c893d77c4fd5c6ebc.woff2 +0 -0
- package/core/resources/fonts/maoken/fcdcb3f4b26b5c1f45fdd151f45e0c6d.woff2 +0 -0
- package/core/resources/fonts/maoken/index.json +0 -59
- package/core/resources/fonts/pangmen/0047cd3053f8c06117a653b73e100391.woff2 +0 -0
- package/core/resources/fonts/pangmen/008870151036457b39ee8794f5bc7a64.woff2 +0 -0
- package/core/resources/fonts/pangmen/01b5355e45274055ad794cc1b1305e69.woff2 +0 -0
- package/core/resources/fonts/pangmen/0756361ea2445ec1c500d354fa0867d0.woff2 +0 -0
- package/core/resources/fonts/pangmen/091cf1201fbbda8dc98c01e775991bab.woff2 +0 -0
- package/core/resources/fonts/pangmen/0c854072dc9998bd02ea8b29b5f1f55e.woff2 +0 -0
- package/core/resources/fonts/pangmen/10f3f7f8da6ab5f882e816c97532a4c6.woff2 +0 -0
- package/core/resources/fonts/pangmen/141229a7039c633c894ea5168d0ae849.woff2 +0 -0
- package/core/resources/fonts/pangmen/1b0b982276f5f93b3c71b3f6b1b81184.woff2 +0 -0
- package/core/resources/fonts/pangmen/1e415e51c4efb3182b87665d726fc423.woff2 +0 -0
- package/core/resources/fonts/pangmen/1f5fb0c8d785813dc765ff889b491361.woff2 +0 -0
- package/core/resources/fonts/pangmen/1fe8065222947d67d4177fe3bdd782cd.woff2 +0 -0
- package/core/resources/fonts/pangmen/229674de0b8d208f607468537d10ca48.woff2 +0 -0
- package/core/resources/fonts/pangmen/27230f128a3708090bed2eb5bb6ad437.woff2 +0 -0
- package/core/resources/fonts/pangmen/2d8f78526cd5d63e22274b3f0e5c4e50.woff2 +0 -0
- package/core/resources/fonts/pangmen/2f441859584ca1d060378be9f1173a6a.woff2 +0 -0
- package/core/resources/fonts/pangmen/319ed7be5128268f3cf297464b305a55.woff2 +0 -0
- package/core/resources/fonts/pangmen/35a41344eec91ef694ca59fda4dc9ccc.woff2 +0 -0
- package/core/resources/fonts/pangmen/3715cbec78511ff67e44fdd363b5fd79.woff2 +0 -0
- package/core/resources/fonts/pangmen/37d468e8e898644f8fddc9f83f04a5b1.woff2 +0 -0
- package/core/resources/fonts/pangmen/384b560d66242e5c1062489020d8749c.woff2 +0 -0
- package/core/resources/fonts/pangmen/38ef10dd61436ebaeb8dada7b827595c.woff2 +0 -0
- package/core/resources/fonts/pangmen/3e8bdfd8597f723100ff7d6b54e803f9.woff2 +0 -0
- package/core/resources/fonts/pangmen/43d57e12e1ec85c68a289d88f920f62e.woff2 +0 -0
- package/core/resources/fonts/pangmen/4c4ee1006529ddcc67e7c195d5ddb2e0.woff2 +0 -0
- package/core/resources/fonts/pangmen/4f65210dd5014352f4c6eb1a791e56c9.woff2 +0 -0
- package/core/resources/fonts/pangmen/5179f5b92b71d655b9094b282ca39161.woff2 +0 -0
- package/core/resources/fonts/pangmen/5282fc1cc80a878d744621a36279a1fa.woff2 +0 -0
- package/core/resources/fonts/pangmen/57604d7bad494a118e0fa9a6c0f1035a.woff2 +0 -0
- package/core/resources/fonts/pangmen/5891eaedeb9999f6b71434efc42407db.woff2 +0 -0
- package/core/resources/fonts/pangmen/592e3b1817378c607c8b6b183c89019a.woff2 +0 -0
- package/core/resources/fonts/pangmen/5c7c16778cf226e25ef39e475a19afa0.woff2 +0 -0
- package/core/resources/fonts/pangmen/5eccbf1ee87f73db786ee0a8441df8a3.woff2 +0 -0
- package/core/resources/fonts/pangmen/606a4091be7a3307a2d9adc4d2206b04.woff2 +0 -0
- package/core/resources/fonts/pangmen/62da615f3cbb7d19ce02973b009ec5b9.woff2 +0 -0
- package/core/resources/fonts/pangmen/63f9972982226af9df16006408160e8a.woff2 +0 -0
- package/core/resources/fonts/pangmen/6702bbfff577fce5bc621a91fdcb78bc.woff2 +0 -0
- package/core/resources/fonts/pangmen/6cd32dbf440a9b7711cc293b19f4c2d7.woff2 +0 -0
- package/core/resources/fonts/pangmen/6ef49a0811c0a0892dfbca6602365e6f.woff2 +0 -0
- package/core/resources/fonts/pangmen/7194cb1fa135d58fee1611bb8915fe25.woff2 +0 -0
- package/core/resources/fonts/pangmen/71baf3daab3248b0748dd187ab2fbc45.woff2 +0 -0
- package/core/resources/fonts/pangmen/7457db009eff249ec587c7d912c5d347.woff2 +0 -0
- package/core/resources/fonts/pangmen/762d1c7a28837c08180123e98dbe8cbf.woff2 +0 -0
- package/core/resources/fonts/pangmen/76e3d855d8684a1ee4d12cf7a572ca78.woff2 +0 -0
- package/core/resources/fonts/pangmen/78a97efdf675a6dcf903b4725de01219.woff2 +0 -0
- package/core/resources/fonts/pangmen/7b42a8cbf34bd2a0820ed81bb4730b6d.woff2 +0 -0
- package/core/resources/fonts/pangmen/7d07b13e8fc6502f0d2e21a7bb87ddb1.woff2 +0 -0
- package/core/resources/fonts/pangmen/7e710c007a48e4410861c67a9a26d4fc.woff2 +0 -0
- package/core/resources/fonts/pangmen/7eb8fe8685f6f2d6f0e223337f3a2b2b.woff2 +0 -0
- package/core/resources/fonts/pangmen/7ec1b00b541c2c2817cf352e2634bf5b.woff2 +0 -0
- package/core/resources/fonts/pangmen/7ffdd7059669ad52af7995b515889eeb.woff2 +0 -0
- package/core/resources/fonts/pangmen/818c6b2f12623b5a43d1036cb7f71b61.woff2 +0 -0
- package/core/resources/fonts/pangmen/81983731abfefd6a400b83b93d9e3665.woff2 +0 -0
- package/core/resources/fonts/pangmen/821ad173f8fd8eccd214241cc651657b.woff2 +0 -0
- package/core/resources/fonts/pangmen/83ee6dce60a5f156da3ad18e5cfb3e6e.woff2 +0 -0
- package/core/resources/fonts/pangmen/87db73da676a2e7b3e640e84187a5c86.woff2 +0 -0
- package/core/resources/fonts/pangmen/89b2edc17dd7ab4332f18b038d268068.woff2 +0 -0
- package/core/resources/fonts/pangmen/8b3f89232252b80f6e12ab91d93fda96.woff2 +0 -0
- package/core/resources/fonts/pangmen/928a7b39a7c4efdca10f70dfcdb917ac.woff2 +0 -0
- package/core/resources/fonts/pangmen/945d03601ca6e8be5f7e6043ecb716a5.woff2 +0 -0
- package/core/resources/fonts/pangmen/97de16fa122ebcbff22956b7b2de2f77.woff2 +0 -0
- package/core/resources/fonts/pangmen/9882677dd482462a6c1c0a1d7efbb15d.woff2 +0 -0
- package/core/resources/fonts/pangmen/9c46188cc1e1711f860fa06d2c29dcc1.woff2 +0 -0
- package/core/resources/fonts/pangmen/a279650fd2f2f115ab30cbbf748f85f9.woff2 +0 -0
- package/core/resources/fonts/pangmen/a3bfd69906b38ab891501ac997bd577d.woff2 +0 -0
- package/core/resources/fonts/pangmen/a4cc4f73c30d1dca3f7abd656705e239.woff2 +0 -0
- package/core/resources/fonts/pangmen/a54d94633b077f678d15b96ad9e6a9c9.woff2 +0 -0
- package/core/resources/fonts/pangmen/ab9bd513cba626dee079d3f8f35da118.woff2 +0 -0
- package/core/resources/fonts/pangmen/b4b057c12d1e44681bdb5c5e92f8e070.woff2 +0 -0
- package/core/resources/fonts/pangmen/b8c1e4b1ab3beb334fa773a50c9221b0.woff2 +0 -0
- package/core/resources/fonts/pangmen/b93617eda1294f0696193c5237320892.woff2 +0 -0
- package/core/resources/fonts/pangmen/bac50a33e26632667ed330c817b37dcf.woff2 +0 -0
- package/core/resources/fonts/pangmen/c31e6efe815ccefa90bebc1fa64aba8b.woff2 +0 -0
- package/core/resources/fonts/pangmen/c75ff5aa44a05db009b0a38d05f4040b.woff2 +0 -0
- package/core/resources/fonts/pangmen/ca70255a9a388b3f33cff49d5abc31f2.woff2 +0 -0
- package/core/resources/fonts/pangmen/cb249c8c31a2bee3d6a68fd1c74c061a.woff2 +0 -0
- package/core/resources/fonts/pangmen/cb898d32532efe5a7933672228bc620c.woff2 +0 -0
- package/core/resources/fonts/pangmen/cc3c33c20e8abd03b9e5acc637985d63.woff2 +0 -0
- package/core/resources/fonts/pangmen/cca20bec40d1a11ede1ec496d22cd026.woff2 +0 -0
- package/core/resources/fonts/pangmen/cedee24be6ea34e35c53c0ce5edd7af0.woff2 +0 -0
- package/core/resources/fonts/pangmen/d42c580643039640037f5c63750ac711.woff2 +0 -0
- package/core/resources/fonts/pangmen/dbe1c94b8d92f8915c33fff55b625716.woff2 +0 -0
- package/core/resources/fonts/pangmen/dced2d67eceeefa7f45ba44854174b8b.woff2 +0 -0
- package/core/resources/fonts/pangmen/dee98b9b0545a42fd3aaa87ec1fa213e.woff2 +0 -0
- package/core/resources/fonts/pangmen/e6ac6bb1654d431fe62556a342b16e52.woff2 +0 -0
- package/core/resources/fonts/pangmen/eb9be6e3e450bf5706308fcec576c6df.woff2 +0 -0
- package/core/resources/fonts/pangmen/ee8cb027810ba5b5d9016774789f747b.woff2 +0 -0
- package/core/resources/fonts/pangmen/f0ecb29938306af8e9117a24eefad319.woff2 +0 -0
- package/core/resources/fonts/pangmen/f1a1a697d45d7f13a71a0a38424a98a7.woff2 +0 -0
- package/core/resources/fonts/pangmen/f203894451810a009d6795f1b0493989.woff2 +0 -0
- package/core/resources/fonts/pangmen/f53b808c0d5afb527499049ba225198e.woff2 +0 -0
- package/core/resources/fonts/pangmen/f6f69823eda331486d1d1a6e676e1d4a.woff2 +0 -0
- package/core/resources/fonts/pangmen/fb1ad0e1ba9ca84b66aa88867ce4109c.woff2 +0 -0
- package/core/resources/fonts/pangmen/index.json +0 -95
package/core/webpack.build.js
CHANGED
|
@@ -1,71 +1,504 @@
|
|
|
1
|
-
|
|
1
|
+
const { merge } = require('webpack-merge');
|
|
2
|
+
const { webpackCommonConfig } = require('./webpack.common.js');
|
|
3
|
+
const webpack = require('webpack');
|
|
4
|
+
const TerserPlugin = require('terser-webpack-plugin');
|
|
5
|
+
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
|
6
|
+
const HtmlInlineScriptPlugin = require('html-inline-script-webpack-plugin');
|
|
7
|
+
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
8
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
9
|
+
const { ZipPlugin } = require('./plugins/ZipPlugin.js');
|
|
10
|
+
const { FflateCompressionPlugin } = require('./plugins/FflateCompressionPlugin.js');
|
|
11
|
+
const { generateAdikteevHtmlWebpackPluginConfig } = require('./utils/generateAdikteevHtmlWebpackPluginConfig.js');
|
|
12
|
+
const { generateBigabidHtmlWebpackPluginConfig } = require('./utils/generateBigabidHtmlWebpackPluginConfig.js');
|
|
13
|
+
const { generateInMobiHtmlWebpackPluginConfig } = require('./utils/generateInMobiHtmlWebpackPluginConfig.js');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const { mergeOptions } = require('./utils/mergeOptions.js');
|
|
16
|
+
const { options } = require('./options.js');
|
|
17
|
+
const { buildDefines } = require('./utils/buildDefines.js');
|
|
18
|
+
const { buildTemplateString } = require('./utils/buildTemplateString.js');
|
|
19
|
+
const { logOptions } = require('./utils/logOptions.js');
|
|
20
|
+
const { injectSDKPlugins } = require('./utils/injectSDKPlugins.js');
|
|
21
|
+
const { resolveChannelFold2Zip } = require('./utils/resolveChannelFold2Zip.js');
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
const META = {
|
|
25
|
+
COMMON_CHARSET: 'utf-8',
|
|
26
|
+
COMMON_VIEWPORT: 'width=device-width,initial-scale=1.0,viewport-fit=cover,maximum-scale=1.0,user-scalable=no',
|
|
27
|
+
MINTEGRAL_VIEWPORT: 'width=device-width,user-scalable=no,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const FontFamily = {
|
|
31
|
+
LIFTOFF: '<style>body{font-family:Roboto,"Helvetica Neue",-apple-system,BlinkMacSystemFont,sans-serif}</style>',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
2
35
|
* HtmlWebpackPlugin beforeEmit 钩子。
|
|
3
36
|
* 在最终 HTML 输出前统一修正 meta 标签:
|
|
4
37
|
* - charset → 统一小写 utf-8
|
|
5
38
|
* - viewport → 统一替换为渠道通道规范值
|
|
6
39
|
* 项目模板无需关心 meta 标签,全部由 devkit 构建时自动处理。
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
40
|
+
*/
|
|
41
|
+
class MetaTagOverridePlugin {
|
|
42
|
+
constructor(adNetwork) {
|
|
43
|
+
this.adNetwork = adNetwork;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
apply(compiler) {
|
|
47
|
+
compiler.hooks.compilation.tap('MetaTagOverridePlugin', (compilation) => {
|
|
48
|
+
HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tap('MetaTagOverridePlugin', (data) => {
|
|
49
|
+
// charset: 统一小写
|
|
50
|
+
data.html = data.html.replace(/<meta\s+charset=["'][^"']*["']\s*\/?>/i, '<meta charset="utf-8" />');
|
|
51
|
+
// viewport: Mintegral 需要 minimum-scale,其他渠道通用
|
|
52
|
+
const viewportContent = this.adNetwork === 'mintegral'
|
|
53
|
+
? META.MINTEGRAL_VIEWPORT
|
|
54
|
+
: META.COMMON_VIEWPORT;
|
|
55
|
+
data.html = data.html.replace(
|
|
56
|
+
/<meta\s+name=["']viewport["'][^>]*\/?>/i,
|
|
57
|
+
`<meta name="viewport" content="${viewportContent}" />`
|
|
58
|
+
);
|
|
59
|
+
// font-family: Liftoff 渠道需要指定系统字体
|
|
60
|
+
if (this.adNetwork === 'liftoff') {
|
|
61
|
+
const fontStyle = FontFamily.LIFTOFF;
|
|
62
|
+
data.html = data.html.replace('</head>', fontStyle + '</head>');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return data;
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** @type {AD_NETWORK[]} */
|
|
72
|
+
/** @type {AD_NETWORK[]} */
|
|
73
|
+
const zipOutputNetworks = [
|
|
74
|
+
'google',
|
|
75
|
+
'pangle',
|
|
76
|
+
'tiktok',
|
|
77
|
+
'vungle',
|
|
78
|
+
'mytarget',
|
|
79
|
+
'mintegral',
|
|
80
|
+
'adikteev',
|
|
81
|
+
'bigabid',
|
|
82
|
+
'inmobi', // InMobi 支持 ZIP 格式(包含 index.html + 资源文件)
|
|
83
|
+
'snapchat',
|
|
84
|
+
'bigoads',
|
|
85
|
+
'liftoff'
|
|
86
|
+
];
|
|
87
|
+
/** @type {AD_NETWORK[]} */
|
|
88
|
+
const zipOutputAllowedNetworks = ['facebook', 'moloco'];
|
|
89
|
+
|
|
90
|
+
/**
|
|
12
91
|
* Creates webpack configuration for production build
|
|
13
92
|
* @param {Partial<import('./index').CLIOptions>} [customOptions] - Custom options to merge with default options
|
|
14
93
|
* @param {Record<string, any>} [customDefines] - Additional defines for webpack.DefinePlugin
|
|
15
94
|
* @param {import('webpack').Configuration} [webpackCustomConfig] - Custom webpack config to merge
|
|
16
95
|
* @returns {import('webpack').Configuration} Final webpack production configuration
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if(adNetwork
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
96
|
+
*/
|
|
97
|
+
function makeWebpackBuildConfig(customOptions, customDefines, webpackCustomConfig) {
|
|
98
|
+
const buildOptions = mergeOptions(options, customOptions);
|
|
99
|
+
logOptions(buildOptions);
|
|
100
|
+
customDefines = customDefines || {};
|
|
101
|
+
webpackCustomConfig = webpackCustomConfig || {};
|
|
102
|
+
|
|
103
|
+
/** @type {AD_NETWORK} */
|
|
104
|
+
const adNetwork = buildOptions['network'];
|
|
105
|
+
|
|
106
|
+
/** @type {AD_PROTOCOL} */
|
|
107
|
+
const adProtocol = buildOptions['protocol'];
|
|
108
|
+
|
|
109
|
+
let outDir = buildTemplateString(buildOptions.outDir, buildOptions);
|
|
110
|
+
|
|
111
|
+
function getFileName() {
|
|
112
|
+
let filename = buildTemplateString(buildOptions.filename, buildOptions);
|
|
113
|
+
|
|
114
|
+
if (adNetwork === 'mintegral') return filename.replace(/\s+/g, '').replace(/[^a-zA-Z0-9]/g, '_').replace('_fullhash_6_', '[fullhash:6]');
|
|
115
|
+
return filename;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const isZipOutput =
|
|
119
|
+
zipOutputNetworks.includes(adNetwork) || (buildOptions.zip && zipOutputAllowedNetworks.includes(adNetwork));
|
|
120
|
+
|
|
121
|
+
const { isChannelFold2Zip, isZipOutputFinal } = resolveChannelFold2Zip({
|
|
122
|
+
isChannelFold2ZipOption: buildOptions.isChannelFold2Zip,
|
|
123
|
+
adNetwork,
|
|
124
|
+
isZipOutput
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
let htmlFileName = '';
|
|
128
|
+
if (adNetwork === 'mintegral') htmlFileName = 'index.html'; // 修改为 index.html
|
|
129
|
+
else if (isZipOutputFinal) htmlFileName = 'index.html';
|
|
130
|
+
else htmlFileName = `${getFileName()}.html`;
|
|
131
|
+
|
|
132
|
+
const metaTags = {
|
|
133
|
+
viewport: META.COMMON_VIEWPORT,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
if (adNetwork === 'mintegral') {
|
|
137
|
+
metaTags['viewport'] = META.MINTEGRAL_VIEWPORT;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!buildOptions.skipRecommendedMeta) {
|
|
141
|
+
metaTags['HandheldFriendly'] = 'True';
|
|
142
|
+
metaTags['cleartype'] = { 'http-equiv': 'cleartype', content: 'on' };
|
|
143
|
+
metaTags['apple-mobile-web-app-capable'] = 'yes';
|
|
144
|
+
metaTags['mobile-web-app-capable'] = 'yes';
|
|
145
|
+
metaTags['X-UA-Compatible'] = { 'http-equiv': 'X-UA-Compatible', content: 'IE=10' };
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let htmlWebpackPluginConfig = {
|
|
149
|
+
template: path.resolve('src/index.html'),
|
|
150
|
+
filename: htmlFileName,
|
|
151
|
+
title: `${buildOptions.name} - ${buildOptions.app}`,
|
|
152
|
+
inlineSource: '.(js|css|png|jpg|webp|svg|xml|atlas|mp3|gif|glb|fbx|obj)$',
|
|
153
|
+
meta: metaTags
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
if (adNetwork === 'adikteev') htmlWebpackPluginConfig = generateAdikteevHtmlWebpackPluginConfig('src/index.html');
|
|
157
|
+
else if (adNetwork === 'bigabid') htmlWebpackPluginConfig = generateBigabidHtmlWebpackPluginConfig('src/index.html');
|
|
158
|
+
else if (adNetwork === 'inmobi')
|
|
159
|
+
htmlWebpackPluginConfig = generateInMobiHtmlWebpackPluginConfig('src/index.html', buildOptions);
|
|
160
|
+
|
|
161
|
+
const webpackConfig = merge(
|
|
162
|
+
webpackCommonConfig,
|
|
163
|
+
{
|
|
164
|
+
mode: 'production',
|
|
165
|
+
stats: 'errors-only',
|
|
166
|
+
optimization: {
|
|
167
|
+
usedExports: true,
|
|
168
|
+
minimize: (buildOptions.obfuscateLevel !== undefined ? buildOptions.obfuscateLevel : 2) >= 1,
|
|
169
|
+
minimizer: [
|
|
170
|
+
new TerserPlugin({
|
|
171
|
+
extractComments: false,
|
|
172
|
+
terserOptions: {
|
|
173
|
+
safari10: true,
|
|
174
|
+
mangle: {
|
|
175
|
+
reserved: ['$'],
|
|
176
|
+
// ⚠️ 不要开启 properties: true,会混淆 Phaser 等框架的属性名导致运行时错误
|
|
177
|
+
// properties: true,
|
|
178
|
+
toplevel: true
|
|
179
|
+
},
|
|
180
|
+
compress: {
|
|
181
|
+
drop_console: true,
|
|
182
|
+
arrows: false,
|
|
183
|
+
drop_debugger: true,
|
|
184
|
+
unused: true,
|
|
185
|
+
dead_code: true,
|
|
186
|
+
// 🔥 增加优化轮数
|
|
187
|
+
passes: 3,
|
|
188
|
+
// 🔥 激进压缩选项
|
|
189
|
+
inline: 3, // 最大内联
|
|
190
|
+
collapse_vars: true, // 折叠变量
|
|
191
|
+
reduce_vars: true, // 减少变量
|
|
192
|
+
hoist_vars: true, // 提升变量
|
|
193
|
+
hoist_funs: true, // 提升函数
|
|
194
|
+
sequences: 20, // 更长的序列化
|
|
195
|
+
properties: true, // 优化属性访问
|
|
196
|
+
conditionals: true, // 优化条件
|
|
197
|
+
comparisons: true, // 优化比较
|
|
198
|
+
booleans: true, // 优化布尔
|
|
199
|
+
loops: true, // 优化循环
|
|
200
|
+
if_return: true, // 优化 if-return
|
|
201
|
+
join_vars: true, // 合并变量
|
|
202
|
+
negate_iife: true, // 否定 IIFE
|
|
203
|
+
side_effects: true, // 移除副作用
|
|
204
|
+
switches: true, // 优化 switch
|
|
205
|
+
typeofs: true, // 优化 typeof
|
|
206
|
+
unsafe: false, // 不使用 unsafe(避免破坏框架)
|
|
207
|
+
keep_fargs: false, // 移除未使用参数
|
|
208
|
+
drop_console: true
|
|
209
|
+
},
|
|
210
|
+
output: {
|
|
211
|
+
comments: false,
|
|
212
|
+
quote_style: 3,
|
|
213
|
+
beautify: false,
|
|
214
|
+
wrap_iife: true,
|
|
215
|
+
ecma: 2015
|
|
216
|
+
},
|
|
217
|
+
toplevel: true,
|
|
218
|
+
keep_classnames: false,
|
|
219
|
+
keep_fnames: false
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
]
|
|
223
|
+
},
|
|
224
|
+
plugins: [
|
|
225
|
+
new HtmlWebpackPlugin(htmlWebpackPluginConfig),
|
|
226
|
+
new MetaTagOverridePlugin(adNetwork),
|
|
227
|
+
|
|
228
|
+
new webpack.DefinePlugin({
|
|
229
|
+
...buildDefines(),
|
|
230
|
+
...buildOptions.defines,
|
|
231
|
+
...customDefines
|
|
232
|
+
}),
|
|
233
|
+
|
|
234
|
+
// For some reason needed for PIXI v8
|
|
235
|
+
new webpack.optimize.LimitChunkCountPlugin({
|
|
236
|
+
maxChunks: 1
|
|
237
|
+
})
|
|
238
|
+
]
|
|
239
|
+
},
|
|
240
|
+
webpackCustomConfig
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
webpackConfig.output.path = path.resolve(outDir);
|
|
244
|
+
|
|
245
|
+
// 根据混淆等级注入 obfuscator loader
|
|
246
|
+
const obfuscateLevel = buildOptions.obfuscateLevel !== undefined ? buildOptions.obfuscateLevel : 2;
|
|
247
|
+
|
|
248
|
+
// 获取需要排除压缩的目录列表
|
|
249
|
+
const excludeCompressDirs = buildOptions.excludeCompressDirs || [];
|
|
250
|
+
|
|
251
|
+
if (obfuscateLevel >= 2) {
|
|
252
|
+
// 构建各等级的 obfuscator 配置
|
|
253
|
+
const obfuscatorOptions = {
|
|
254
|
+
// 通用基础配置
|
|
255
|
+
target: 'browser',
|
|
256
|
+
sourceMap: false,
|
|
257
|
+
selfDefending: false,
|
|
258
|
+
renameProperties: false,
|
|
259
|
+
disableConsoleOutput: true,
|
|
260
|
+
splitStrings: false,
|
|
261
|
+
unicodeEscapeSequence: false
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
if (obfuscateLevel === 2) {
|
|
265
|
+
// 等级2:基础混淆(控制流平坦化 + 字符串数组)
|
|
266
|
+
Object.assign(obfuscatorOptions, {
|
|
267
|
+
controlFlowFlattening: true,
|
|
268
|
+
controlFlowFlatteningThreshold: 0.75,
|
|
269
|
+
deadCodeInjection: false,
|
|
270
|
+
stringArray: true,
|
|
271
|
+
stringArrayThreshold: 0.75,
|
|
272
|
+
stringArrayEncoding: ['base64'],
|
|
273
|
+
stringArrayIndexShift: true,
|
|
274
|
+
stringArrayRotate: true,
|
|
275
|
+
stringArrayShuffle: true,
|
|
276
|
+
stringArrayWrappersCount: 2,
|
|
277
|
+
stringArrayWrappersChainedCalls: true,
|
|
278
|
+
stringArrayWrappersType: 'function',
|
|
279
|
+
stringArrayCallsTransform: true,
|
|
280
|
+
stringArrayCallsTransformThreshold: 0.75,
|
|
281
|
+
transformObjectKeys: true,
|
|
282
|
+
identifierNamesGenerator: 'hexadecimal'
|
|
283
|
+
});
|
|
284
|
+
} else if (obfuscateLevel === 3) {
|
|
285
|
+
// 等级3:在等级2基础上增加死代码注入
|
|
286
|
+
Object.assign(obfuscatorOptions, {
|
|
287
|
+
controlFlowFlattening: true,
|
|
288
|
+
controlFlowFlatteningThreshold: 0.75,
|
|
289
|
+
deadCodeInjection: true,
|
|
290
|
+
deadCodeInjectionThreshold: 0.4,
|
|
291
|
+
stringArray: true,
|
|
292
|
+
stringArrayThreshold: 0.75,
|
|
293
|
+
stringArrayEncoding: ['base64'],
|
|
294
|
+
stringArrayIndexShift: true,
|
|
295
|
+
stringArrayRotate: true,
|
|
296
|
+
stringArrayShuffle: true,
|
|
297
|
+
stringArrayWrappersCount: 2,
|
|
298
|
+
stringArrayWrappersChainedCalls: true,
|
|
299
|
+
stringArrayWrappersType: 'function',
|
|
300
|
+
stringArrayCallsTransform: true,
|
|
301
|
+
stringArrayCallsTransformThreshold: 0.75,
|
|
302
|
+
transformObjectKeys: true,
|
|
303
|
+
identifierNamesGenerator: 'hexadecimal'
|
|
304
|
+
});
|
|
305
|
+
} else if (obfuscateLevel === 4) {
|
|
306
|
+
// 等级4:最高强度混淆
|
|
307
|
+
Object.assign(obfuscatorOptions, {
|
|
308
|
+
controlFlowFlattening: true,
|
|
309
|
+
controlFlowFlatteningThreshold: 1,
|
|
310
|
+
deadCodeInjection: true,
|
|
311
|
+
deadCodeInjectionThreshold: 0.5,
|
|
312
|
+
stringArray: true,
|
|
313
|
+
stringArrayThreshold: 1,
|
|
314
|
+
stringArrayEncoding: ['rc4'],
|
|
315
|
+
stringArrayIndexShift: true,
|
|
316
|
+
stringArrayRotate: true,
|
|
317
|
+
stringArrayShuffle: true,
|
|
318
|
+
stringArrayWrappersCount: 3,
|
|
319
|
+
stringArrayWrappersChainedCalls: true,
|
|
320
|
+
stringArrayWrappersType: 'function',
|
|
321
|
+
stringArrayCallsTransform: true,
|
|
322
|
+
stringArrayCallsTransformThreshold: 1,
|
|
323
|
+
transformObjectKeys: true,
|
|
324
|
+
identifierNamesGenerator: 'hexadecimal',
|
|
325
|
+
splitStrings: true,
|
|
326
|
+
splitStringsChunkLength: 5,
|
|
327
|
+
unicodeEscapeSequence: true,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
console.log(`Obfuscation level: ${obfuscateLevel} (${['', 'terser-only', 'basic', 'dead-code', 'maximum'][obfuscateLevel]})`);
|
|
332
|
+
|
|
333
|
+
// 构建exclude数组,包含node_modules和用户指定的排除目录
|
|
334
|
+
const excludePatterns = [];
|
|
335
|
+
if (excludeCompressDirs.length > 0) {
|
|
336
|
+
excludeCompressDirs.forEach(dir => {
|
|
337
|
+
excludePatterns.push(path.resolve(dir));
|
|
338
|
+
});
|
|
339
|
+
console.log(`ℹ️ Excluding directories from compression: ${excludeCompressDirs.join(', ')}`);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
webpackConfig.module.rules.push({
|
|
343
|
+
test: /\.(js|ts)$/,
|
|
344
|
+
include: [path.resolve('src')],
|
|
345
|
+
exclude: excludePatterns,
|
|
346
|
+
enforce: 'post',
|
|
347
|
+
use: {
|
|
348
|
+
loader: require.resolve('webpack-obfuscator/dist/loader'),
|
|
349
|
+
options: obfuscatorOptions
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
} else if (obfuscateLevel === 1) {
|
|
353
|
+
console.log('Obfuscation level: 1 (terser-only)');
|
|
354
|
+
} else {
|
|
355
|
+
console.log('Obfuscation level: 0 (no minimize/obfuscate)');
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Adikteev 需要单独提取 CSS 为 style.css,替换默认的 style-loader
|
|
359
|
+
if (adNetwork === 'adikteev') {
|
|
360
|
+
const cssRuleIndex = webpackConfig.module.rules.findIndex(rule =>
|
|
361
|
+
rule.test && rule.test.toString().includes('\\.css')
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
if (cssRuleIndex !== -1) {
|
|
365
|
+
webpackConfig.module.rules[cssRuleIndex] = {
|
|
366
|
+
test: /\.css$/,
|
|
367
|
+
use: [MiniCssExtractPlugin.loader, 'css-loader']
|
|
368
|
+
};
|
|
369
|
+
console.log('✅ Adikteev: CSS will be extracted to style.css');
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// 决定是否内联 JS 到 HTML
|
|
374
|
+
// 以下渠道需要分离 JS 文件,不使用 HtmlInlineScriptPlugin:
|
|
375
|
+
// - mintegral: 需要独立的 JS 文件
|
|
376
|
+
// - adikteev: 需要 creative.js 上传到 CDN
|
|
377
|
+
// - bigabid: 需要 main.js 上传到 CDN
|
|
378
|
+
// - facebook (ZIP 模式): Facebook ZIP 格式需要分离文件
|
|
379
|
+
if (
|
|
380
|
+
adNetwork !== 'mintegral' &&
|
|
381
|
+
adNetwork !== 'adikteev' &&
|
|
382
|
+
adNetwork !== 'bigabid' &&
|
|
383
|
+
!(isZipOutputFinal && adNetwork === 'facebook')
|
|
384
|
+
)
|
|
385
|
+
webpackConfig.plugins.push(new HtmlInlineScriptPlugin());
|
|
386
|
+
|
|
387
|
+
// 注入渠道 SDK 插件(公共逻辑)
|
|
388
|
+
injectSDKPlugins(webpackConfig, {
|
|
389
|
+
network: adNetwork,
|
|
390
|
+
protocol: adProtocol,
|
|
391
|
+
orientation: buildOptions.orientation
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
if (isZipOutputFinal) {
|
|
395
|
+
if (adNetwork === 'tiktok') {
|
|
396
|
+
webpackConfig.plugins.push(
|
|
397
|
+
new CopyWebpackPlugin({
|
|
398
|
+
patterns: [{ from: path.join(__dirname, 'resources', 'tiktok-config.json'), to: 'config.json' }]
|
|
399
|
+
})
|
|
400
|
+
);
|
|
401
|
+
} else if (adNetwork === 'snapchat') {
|
|
402
|
+
const tmpConfigPath = path.join(__dirname, 'resources', 'snapchat-config.json');
|
|
403
|
+
|
|
404
|
+
webpackConfig.plugins.push(
|
|
405
|
+
new CopyWebpackPlugin({
|
|
406
|
+
patterns: [{ from: tmpConfigPath, to: 'config.json' }]
|
|
407
|
+
})
|
|
408
|
+
);
|
|
409
|
+
} else if (adNetwork === 'bigoads') {
|
|
410
|
+
// BigoAds 要求输出 ZIP 包,包含 index.html 和 config.json
|
|
411
|
+
// SDK 注入已在 injectSDKPlugins 中处理
|
|
412
|
+
webpackConfig.plugins.push(
|
|
413
|
+
new CopyWebpackPlugin({
|
|
414
|
+
patterns: [{ from: path.join(__dirname, 'resources', 'bigoads-config.json'), to: 'config.json' }]
|
|
415
|
+
})
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
webpackConfig.plugins.push(
|
|
420
|
+
new ZipPlugin({
|
|
421
|
+
filename: isChannelFold2Zip ? adNetwork : getFileName(),
|
|
422
|
+
path: path.resolve(outDir),
|
|
423
|
+
cleanTempFolder: true // 🗑️ 生成 zip 后删除临时文件夹
|
|
424
|
+
})
|
|
425
|
+
);
|
|
426
|
+
|
|
427
|
+
webpackConfig.output.path = path.resolve(outDir, adNetwork);
|
|
428
|
+
if (adNetwork === 'adikteev') {
|
|
429
|
+
webpackConfig.output.filename = 'creative.js';
|
|
430
|
+
// Adikteev 需要将 CSS 单独提取为 style.css 文件
|
|
431
|
+
webpackConfig.plugins.push(
|
|
432
|
+
new MiniCssExtractPlugin({
|
|
433
|
+
filename: 'style.css'
|
|
434
|
+
})
|
|
435
|
+
);
|
|
436
|
+
} else if (adNetwork === 'bigabid') webpackConfig.output.filename = 'main.js';
|
|
437
|
+
else if (adNetwork === 'inmobi') webpackConfig.output.filename = 'main.js';
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// 添加 fflate 压缩插件(仅在打正式包时生效)
|
|
441
|
+
if (buildOptions.fflateCompression) {
|
|
442
|
+
console.log('✅ fflate compression enabled (production build only)');
|
|
443
|
+
webpackConfig.plugins.push(
|
|
444
|
+
new FflateCompressionPlugin({
|
|
445
|
+
enabled: true,
|
|
446
|
+
level: 9,
|
|
447
|
+
keepOriginal: false,
|
|
448
|
+
logStats: true,
|
|
449
|
+
googlePlayUrl: buildOptions.googlePlayUrl,
|
|
450
|
+
appStoreUrl: buildOptions.appStoreUrl,
|
|
451
|
+
})
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return webpackConfig;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
64
459
|
* Runs webpack production build
|
|
65
460
|
* @param {import('webpack').Configuration} [webpackConfig] - Webpack configuration to use, creates default if not provided
|
|
66
461
|
* @param {Partial<import('./index').CLIOptions>} [customOptions] - Custom options to merge with default options
|
|
67
462
|
* @param {Record<string, any>} [customDefines] - Additional defines for webpack.DefinePlugin
|
|
68
463
|
* @param {import('webpack').Configuration} [webpackCustomConfig] - Custom webpack config to merge
|
|
69
|
-
*/
|
|
70
|
-
|
|
71
|
-
|
|
464
|
+
*/
|
|
465
|
+
function runBuild(webpackConfig, customOptions, customDefines, webpackCustomConfig) {
|
|
466
|
+
return new Promise((resolve, reject) => {
|
|
467
|
+
if (!webpackConfig) webpackConfig = makeWebpackBuildConfig(customOptions, customDefines, webpackCustomConfig);
|
|
468
|
+
|
|
469
|
+
const compiler = webpack(webpackConfig);
|
|
470
|
+
compiler.run((err, stats) => {
|
|
471
|
+
if (err) {
|
|
472
|
+
console.error('Build failed:', err.stack || err);
|
|
473
|
+
if (err.details) {
|
|
474
|
+
console.error('Error details:', err.details);
|
|
475
|
+
}
|
|
476
|
+
return reject(err);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (stats.hasErrors()) {
|
|
480
|
+
const errors = stats.compilation.errors;
|
|
481
|
+
console.error(`\n❌ Build finished with ${errors.length} error(s):\n`);
|
|
482
|
+
|
|
483
|
+
// 打印每个错误的详细信息
|
|
484
|
+
errors.forEach((error, index) => {
|
|
485
|
+
console.error(`\n[Error ${index + 1}/${errors.length}]`);
|
|
486
|
+
console.error(error.message || error);
|
|
487
|
+
if (error.stack) {
|
|
488
|
+
console.error(error.stack);
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
// 拒绝 Promise 时传递格式化的错误消息
|
|
493
|
+
const errorMessage = errors.map((e, i) => `[${i + 1}] ${e.message || e}`).join('\n');
|
|
494
|
+
reject(new Error(`Webpack build failed with ${errors.length} error(s):\n${errorMessage}`));
|
|
495
|
+
} else {
|
|
496
|
+
console.log(`Build successful!`);
|
|
497
|
+
resolve();
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
exports.makeWebpackBuildConfig = makeWebpackBuildConfig;
|
|
504
|
+
exports.runBuild = runBuild;
|