diff --git a/lib/h5/uni.config.js b/lib/h5/uni.config.js index 60be35d01b94deb343aafabbe21646af88cc27ee..0c1125fa0925bc0f907fe326b8e66b2af7372248 100644 --- a/lib/h5/uni.config.js +++ b/lib/h5/uni.config.js @@ -19,12 +19,13 @@ function transform(content) { } function getIndexCssPath(assetsDir, template) { + const CopyWebpackPluginVersion = Number(require('copy-webpack-plugin/package.json').version.split('.')[0]) const VUE_APP_INDEX_CSS_HASH = process.env.VUE_APP_INDEX_CSS_HASH if (VUE_APP_INDEX_CSS_HASH) { try { const templateContent = fs.readFileSync(getTemplatePath(template)) if (/\bVUE_APP_INDEX_CSS_HASH\b/.test(templateContent)) { - return path.join(assetsDir, `[name].${VUE_APP_INDEX_CSS_HASH}.[ext]`) + return path.join(assetsDir, `[name].${VUE_APP_INDEX_CSS_HASH}${CopyWebpackPluginVersion > 5 ? '' : '.'}[ext]`) } } catch (e) {} } diff --git a/packages/uni-app-plus/lib/uni.config.js b/packages/uni-app-plus/lib/uni.config.js index 2241958b9442940c5d5e77ea0d4932b7abbb5ba9..2434bb6a90c5a7c34a0b006a92dea2c8f9ee83d3 100644 --- a/packages/uni-app-plus/lib/uni.config.js +++ b/packages/uni-app-plus/lib/uni.config.js @@ -6,12 +6,17 @@ const COMPONENTS_DIR_NAME = 'wxcomponents' function getComponentsCopyOption () { if (process.env.UNI_OUTPUT_TMP_DIR) { // TODO v3不需要,即将废弃 const componentsDir = path.resolve(process.env.UNI_INPUT_DIR, COMPONENTS_DIR_NAME) + const CopyWebpackPluginVersion = Number(require('copy-webpack-plugin/package.json').version.split('.')[0]) if (fs.existsSync(componentsDir)) { - return { + const ignore = ['**/*.vue', '**/*.css'] + return Object.assign({ from: componentsDir, - to: COMPONENTS_DIR_NAME, - ignore: ['**/*.vue', '**/*.css'] - } + to: COMPONENTS_DIR_NAME + }, CopyWebpackPluginVersion > 5 ? { + globOptions: { ignore } + } : { + ignore + }) } } } diff --git a/packages/uni-mp-qq/lib/uni.config.js b/packages/uni-mp-qq/lib/uni.config.js index 96bbb194af1b21d0dad4bc757664fca4617dcea9..4d721528526e9e925d5cb37f97ebf13f15d4af0f 100644 --- a/packages/uni-mp-qq/lib/uni.config.js +++ b/packages/uni-mp-qq/lib/uni.config.js @@ -22,6 +22,7 @@ module.exports = { subPackages: true }, copyWebpackOptions (platformOptions, vueOptions) { + const CopyWebpackPluginVersion = Number(require('copy-webpack-plugin/package.json').version.split('.')[0]) const copyOptions = [ // 'sitemap.json', // 'ext.json', @@ -31,21 +32,29 @@ module.exports = { workers && copyOptions.push(workers) const wxcomponentsDir = path.resolve(process.env.UNI_INPUT_DIR, COMPONENTS_DIR_NAME) + const ignore = ['**/*.vue', '**/*.css'] // v3 会自动转换生成vue,css文件,需要过滤 + if (fs.existsSync(wxcomponentsDir)) { - copyOptions.push({ + copyOptions.push(Object.assign({ from: wxcomponentsDir, - to: COMPONENTS_DIR_NAME, - ignore: ['**/*.vue', '**/*.css'] // v3 会自动转换生成vue,css文件,需要过滤 - }) + to: COMPONENTS_DIR_NAME + }, CopyWebpackPluginVersion > 5 ? { + globOptions: { ignore } + } : { + ignore + })) } global.uniModules.forEach(module => { const wxcomponentsDir = path.resolve(process.env.UNI_INPUT_DIR, 'uni_modules', module, COMPONENTS_DIR_NAME) if (fs.existsSync(wxcomponentsDir)) { - copyOptions.push({ + copyOptions.push(Object.assign({ from: wxcomponentsDir, - to: 'uni_modules/' + module + '/' + COMPONENTS_DIR_NAME, - ignore: ['**/*.vue', '**/*.css'] // v3 会自动转换生成vue,css文件,需要过滤 - }) + to: 'uni_modules/' + module + '/' + COMPONENTS_DIR_NAME + }, CopyWebpackPluginVersion > 5 ? { + globOptions: { ignore } + } : { + ignore + })) } }) return copyOptions diff --git a/packages/uni-mp-weixin/lib/uni.config.js b/packages/uni-mp-weixin/lib/uni.config.js index 562d4ccf4febe843cf3453b115b04a57a8e64b04..3c5b09c64225d241aaa619414a24e49824dc3470 100644 --- a/packages/uni-mp-weixin/lib/uni.config.js +++ b/packages/uni-mp-weixin/lib/uni.config.js @@ -24,12 +24,13 @@ module.exports = { darkmode: true }, copyWebpackOptions (platformOptions, vueOptions) { + const CopyWebpackPluginVersion = Number(require('copy-webpack-plugin/package.json').version.split('.')[0]) const copyOptions = [ 'theme.json', 'sitemap.json', 'ext.json', 'custom-tab-bar', - 'functional-pages', + 'functional-pages', 'project.private.config.json' ] @@ -46,25 +47,32 @@ module.exports = { const manifestConfig = process.UNI_MANIFEST const weixinConfig = manifestConfig['mp-weixin'] || {} const copyWxComponentsOnDemandSwitch = !!weixinConfig.copyWxComponentsOnDemand // 默认值false + const ignore = ['**/*.vue', '**/*.css'] // v3 会自动转换生成vue,css文件,需要过滤 if (!copyWxComponentsOnDemandSwitch) { const wxcomponentsDir = path.resolve(process.env.UNI_INPUT_DIR, COMPONENTS_DIR_NAME) if (fs.existsSync(wxcomponentsDir)) { - copyOptions.push({ + copyOptions.push(Object.assign({ from: wxcomponentsDir, - to: COMPONENTS_DIR_NAME, - ignore: ['**/*.vue', '**/*.css'] // v3 会自动转换生成vue,css文件,需要过滤 - }) + to: COMPONENTS_DIR_NAME + }, CopyWebpackPluginVersion > 5 ? { + globOptions: { ignore } + } : { + ignore + })) } } global.uniModules.forEach(module => { const wxcomponentsDir = path.resolve(process.env.UNI_INPUT_DIR, 'uni_modules', module, COMPONENTS_DIR_NAME) if (fs.existsSync(wxcomponentsDir)) { - copyOptions.push({ + copyOptions.push(Object.assign({ from: wxcomponentsDir, - to: 'uni_modules/' + module + '/' + COMPONENTS_DIR_NAME, - ignore: ['**/*.vue', '**/*.css'] // v3 会自动转换生成vue,css文件,需要过滤 - }) + to: 'uni_modules/' + module + '/' + COMPONENTS_DIR_NAME + }, CopyWebpackPluginVersion > 5 ? { + globOptions: { ignore } + } : { + ignore + })) } }) return copyOptions diff --git a/packages/uni-quickapp-native/lib/configure-webpack.js b/packages/uni-quickapp-native/lib/configure-webpack.js index d6d5cc4df3b4a32ab0e7374ce8be462716b2b7fd..813c6a5d38b615e87af27effe58795012f55162f 100644 --- a/packages/uni-quickapp-native/lib/configure-webpack.js +++ b/packages/uni-quickapp-native/lib/configure-webpack.js @@ -2,6 +2,7 @@ const path = require('path') const webpack = require('webpack') const CopyPlugin = require('copy-webpack-plugin') +const CopyPluginVersion = Number(require('copy-webpack-plugin/package.json').version.split('.')[0]) const HandlerPlugin = require('@hap-toolkit/packager/lib/plugin/handler-plugin') const ZipPlugin = require('@hap-toolkit/packager/lib/plugin/zip-plugin') @@ -39,6 +40,11 @@ function genPriorities (entryPagePath) { const uniCloudPath = require.resolve('@dcloudio/vue-cli-plugin-uni/packages/uni-cloud/dist/index.js') +const patterns = [{ + from: path.resolve(__dirname, '../dist/' + dslFilename), + to: 'dsl.js' +}] + module.exports = { devtool: false, entry () { @@ -77,10 +83,7 @@ module.exports = { new webpack.ProvidePlugin({ uniCloud: [uniCloudPath, 'default'] }), - new CopyPlugin([{ - from: path.resolve(__dirname, '../dist/' + dslFilename), - to: 'dsl.js' - }]), + new CopyPlugin(CopyPluginVersion > 5 ? { patterns } : patterns), new HandlerPlugin({}), new Css2jsonPlugin(), new InstVuePlugin(), @@ -101,4 +104,4 @@ module.exports = { }), new NotifyPlugin() ] -} +} diff --git a/packages/vue-cli-plugin-hbuilderx/build/css-loader.conf.js b/packages/vue-cli-plugin-hbuilderx/build/css-loader.conf.js index 87bd71ca3983ba553febee1f9cfc1d63fd0cd08c..e0ce80eee0fb365716bfa3469d251527e7836568 100644 --- a/packages/vue-cli-plugin-hbuilderx/build/css-loader.conf.js +++ b/packages/vue-cli-plugin-hbuilderx/build/css-loader.conf.js @@ -1,5 +1,6 @@ const fs = require('fs') const path = require('path') +const webpack = require('webpack') const { getPlatformScss, @@ -7,10 +8,6 @@ const { nvueCssPreprocessOptions } = require('@dcloudio/uni-cli-shared') -const { - sassLoaderVersion -} = require('@dcloudio/uni-cli-shared/lib/scss') - const nvueStyleLoader = { loader: '@dcloudio/vue-cli-plugin-hbuilderx/packages/webpack-uni-nvue-loader/lib/style' } @@ -20,27 +17,33 @@ const preprocessLoader = { options: nvueCssPreprocessOptions } +const options = { + sourceMap: false +} +const plugins = [ + require('postcss-import')({ + resolve (id, basedir, importOptions) { + if (id.startsWith('~@/')) { + return path.resolve(process.env.UNI_INPUT_DIR, id.substr(3)) + } else if (id.startsWith('@/')) { + return path.resolve(process.env.UNI_INPUT_DIR, id.substr(2)) + } else if (id.startsWith('/') && !id.startsWith('//')) { + return path.resolve(process.env.UNI_INPUT_DIR, id.substr(1)) + } + return id + } + }), + require('@dcloudio/vue-cli-plugin-uni/packages/postcss') +] +if (webpack.version[0] > 4) { + options.postcssOptions = { plugins } +} else { + options.parser = require('postcss-comment') + options.plugins = plugins +} const postcssLoader = { loader: 'postcss-loader', - options: { - sourceMap: false, - parser: require('postcss-comment'), - plugins: [ - require('postcss-import')({ - resolve (id, basedir, importOptions) { - if (id.startsWith('~@/')) { - return path.resolve(process.env.UNI_INPUT_DIR, id.substr(3)) - } else if (id.startsWith('@/')) { - return path.resolve(process.env.UNI_INPUT_DIR, id.substr(2)) - } else if (id.startsWith('/') && !id.startsWith('//')) { - return path.resolve(process.env.UNI_INPUT_DIR, id.substr(1)) - } - return id - } - }), - require('@dcloudio/vue-cli-plugin-uni/packages/postcss') - ] - } + options } // sass 全局变量 @@ -71,25 +74,15 @@ const sassLoader = { } } -if (sassLoaderVersion < 8) { - scssLoader.options.data = sassData - scssLoader.options.outputStyle = 'expanded' - - sassLoader.options.data = sassData - sassLoader.options.outputStyle = 'expanded' - sassLoader.options.indentedSyntax = true -} else { - const name = sassLoaderVersion >= 9 ? 'additionalData' : 'prependData' - scssLoader.options[name] = sassData - scssLoader.options.sassOptions = { - outputStyle: 'expanded' - } +scssLoader.options.prependData = sassData +scssLoader.options.sassOptions = { + outputStyle: 'expanded' +} - sassLoader.options[name] = sassData - sassLoader.options.sassOptions = { - outputStyle: 'expanded', - indentedSyntax: true - } +sassLoader.options.prependData = sassData +sassLoader.options.sassOptions = { + outputStyle: 'expanded', + indentedSyntax: true } const lessLoader = { @@ -143,4 +136,4 @@ module.exports = [{ }, { test: /\.styl(us)?$/, oneOf: createOneOf(stylusLoader) -}] +}] diff --git a/packages/vue-cli-plugin-hbuilderx/build/webpack.nvue.conf.js b/packages/vue-cli-plugin-hbuilderx/build/webpack.nvue.conf.js index 89c7053cbc1c0f5b15eb4836a5e28d52f2a2989c..4f572e5037c71cc941849046b3a19a847fd0398a 100644 --- a/packages/vue-cli-plugin-hbuilderx/build/webpack.nvue.conf.js +++ b/packages/vue-cli-plugin-hbuilderx/build/webpack.nvue.conf.js @@ -3,6 +3,7 @@ const path = require('path') const webpack = require('webpack') const VueLoaderPlugin = require('@dcloudio/vue-cli-plugin-uni/packages/vue-loader/lib/plugin') const CopyWebpackPlugin = require('copy-webpack-plugin') +const CopyWebpackPluginVersion = Number(require('copy-webpack-plugin/package.json').version.split('.')[0]) const TerserPlugin = require('terser-webpack-plugin') const { @@ -112,7 +113,10 @@ if (process.env.NODE_ENV === 'development') { // const excludeModuleReg = /node_modules(?!(\/|\\).*(weex).*)/ -const rules = [{ +const rules = [webpack.version[0] > 4 ? { + test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i, + type: 'asset' +} : { test: /\.(png|jpg|gif|ttf|eot|woff|woff2)$/i, use: [fileLoader] }, { @@ -194,7 +198,7 @@ rules.unshift({ if (process.env.UNI_USING_V3_NATIVE) { try { const automatorJson = require.resolve('@dcloudio/uni-automator/dist/automator.json') - plugins.push(new CopyWebpackPlugin([{ + const patterns = [{ from: automatorJson, to: '../.automator/' + (process.env.UNI_SUB_PLATFORM || process.env.UNI_PLATFORM) + '/.automator.json', @@ -207,15 +211,16 @@ if (process.env.UNI_USING_V3_NATIVE) { } return '' } - }])) - } catch (e) {} + }] + plugins.push(new CopyWebpackPlugin(CopyWebpackPluginVersion > 5 ? { patterns } : patterns)) + } catch (e) { } } if (process.env.UNI_USING_NATIVE || process.env.UNI_USING_V3_NATIVE) { plugins.push(new WebpackUniMPPlugin()) const assetsDir = 'static' const hybridDir = 'hybrid/html' - const array = [{ + const patterns = [{ from: path.resolve(process.env.UNI_INPUT_DIR, assetsDir), to: assetsDir }] @@ -223,7 +228,7 @@ if (process.env.UNI_USING_NATIVE || process.env.UNI_USING_V3_NATIVE) { if (!process.env.UNI_AUTOMATOR_WS_ENDPOINT) { const androidPrivacyPath = path.resolve(process.env.UNI_INPUT_DIR, 'androidPrivacy.json') if (fs.existsSync(androidPrivacyPath)) { - array.push({ + patterns.push({ from: androidPrivacyPath, to: 'androidPrivacy.json' }) @@ -231,7 +236,7 @@ if (process.env.UNI_USING_NATIVE || process.env.UNI_USING_V3_NATIVE) { } const hybridHtmlPath = path.resolve(process.env.UNI_INPUT_DIR, hybridDir) if (fs.existsSync(hybridHtmlPath)) { - array.push({ + patterns.push({ from: hybridHtmlPath, to: hybridDir }) @@ -242,7 +247,7 @@ if (process.env.UNI_USING_NATIVE || process.env.UNI_USING_V3_NATIVE) { const assets = modules + module + '/' + assetsDir const assetsPath = path.resolve(process.env.UNI_INPUT_DIR, assets) if (fs.existsSync(assetsPath)) { - array.push({ + patterns.push({ from: assetsPath, to: assets }) @@ -250,7 +255,7 @@ if (process.env.UNI_USING_NATIVE || process.env.UNI_USING_V3_NATIVE) { const hybridHtml = modules + module + '/' + hybridDir const hybridHtmlPath = path.resolve(process.env.UNI_INPUT_DIR, hybridHtml) if (fs.existsSync(hybridHtmlPath)) { - array.push({ + patterns.push({ from: hybridHtmlPath, to: hybridHtml }) @@ -258,12 +263,12 @@ if (process.env.UNI_USING_NATIVE || process.env.UNI_USING_V3_NATIVE) { }) if (process.env.UNI_USING_NVUE_COMPILER) { - array.push({ + patterns.push({ from: path.resolve(getTemplatePath(), 'common'), to: process.env.UNI_OUTPUT_DIR }) } else if (process.env.UNI_USING_V3_NATIVE) { - array.push({ + patterns.push({ from: path.resolve(getTemplatePath(), 'weex'), to: process.env.UNI_OUTPUT_DIR }) @@ -275,7 +280,7 @@ if (process.env.UNI_USING_NATIVE || process.env.UNI_USING_V3_NATIVE) { 'weapp-tools/template/v8' ) } - array.push({ + patterns.push({ from: nativeTemplatePath, to: process.env.UNI_OUTPUT_DIR }, { @@ -284,15 +289,17 @@ if (process.env.UNI_USING_NATIVE || process.env.UNI_USING_V3_NATIVE) { 'weapp-tools/template/common' ), to: process.env.UNI_OUTPUT_DIR, - ignore: [ - '*.js', - '*.json', - '__uniapppicker.html', - '__uniappview.html' - ] + globOptions: { + ignore: [ + '*.js', + '*.json', + '__uniapppicker.html', + '__uniappview.html' + ] + } }) } - plugins.push(new CopyWebpackPlugin(array)) + plugins.push(new CopyWebpackPlugin(CopyWebpackPluginVersion > 5 ? { patterns } : patterns)) } try { @@ -305,7 +312,7 @@ try { dir: process.env.UNI_INPUT_DIR })) } -} catch (e) {} +} catch (e) { } module.exports = function () { return { @@ -322,8 +329,7 @@ module.exports = function () { performance: { hints: false }, - optimization: { - namedModules: false, + optimization: Object.assign({ minimizer: [ new TerserPlugin({ terserOptions: { @@ -333,7 +339,7 @@ module.exports = function () { } }) ] - }, + }, webpack.version[0] > 4 ? {} : { namedModules: false }), output: { path: process.env.UNI_OUTPUT_DIR, filename: '[name].js' @@ -377,7 +383,7 @@ module.exports = function () { reasons: true, errorDetails: true }, - node: { + node: webpack.version[0] > 4 ? false : { global: false, Buffer: false, __filename: false, diff --git a/packages/vue-cli-plugin-hbuilderx/packages/webpack-app-plus-nvue-plugin/index.js b/packages/vue-cli-plugin-hbuilderx/packages/webpack-app-plus-nvue-plugin/index.js index c907cad89c8c60d6006f6325f827d17e5f587325..03f0f003296b14bacffe48d7a59e38fabf4ad7f5 100644 --- a/packages/vue-cli-plugin-hbuilderx/packages/webpack-app-plus-nvue-plugin/index.js +++ b/packages/vue-cli-plugin-hbuilderx/packages/webpack-app-plus-nvue-plugin/index.js @@ -14,13 +14,10 @@ class WebpackAppPlusNVuePlugin { const changedFiles = [] compiler.hooks.emit.tapAsync('webpack-uni-nvue', (compilation, callback) => { changedFiles.length = 0 - const changedChunks = compilation.chunks.filter(chunk => { + compilation.chunks.forEach(chunk => { const oldVersion = chunkVersions[chunk.name] chunkVersions[chunk.name] = chunk.hash - return chunk.hash !== oldVersion - }) - changedChunks.map(chunk => { - if (Array.isArray(chunk.files)) { + if (chunk.hash !== oldVersion && Array.isArray(chunk.files)) { chunk.files.forEach(file => { !changedFiles.includes(file) && (changedFiles.push(file)) }) diff --git a/packages/vue-cli-plugin-hbuilderx/packages/webpack-app-plus-plugin/index.js b/packages/vue-cli-plugin-hbuilderx/packages/webpack-app-plus-plugin/index.js index b99f48b934c87679d015baea5f11a9328dfb3840..d004f0818404e2fcdc70c749dd7be4312d263e3a 100644 --- a/packages/vue-cli-plugin-hbuilderx/packages/webpack-app-plus-plugin/index.js +++ b/packages/vue-cli-plugin-hbuilderx/packages/webpack-app-plus-plugin/index.js @@ -44,13 +44,10 @@ class WebpackAppPlusPlugin { }) compiler.hooks.emit.tapAsync('WebpackAppPlusPlugin', (compilation, callback) => { - const changedChunks = compilation.chunks.filter(chunk => { + compilation.chunks.forEach(chunk => { const oldVersion = chunkVersions[chunk.name] chunkVersions[chunk.name] = chunk.hash - return chunk.hash !== oldVersion - }) - changedChunks.map(chunk => { - if (Array.isArray(chunk.files)) { + if (chunk.hash !== oldVersion && Array.isArray(chunk.files)) { chunk.files.forEach(file => { if (isAppService) { !serviceChangedFiles.includes(file) && (serviceChangedFiles.push(file)) diff --git a/packages/vue-cli-plugin-uni/commands/build.js b/packages/vue-cli-plugin-uni/commands/build.js index 9fc3f402e7a9633baf3cd25960755da9c0e2771e..0b64298d0bb05a97447db6204f06f545fa066de6 100644 --- a/packages/vue-cli-plugin-uni/commands/build.js +++ b/packages/vue-cli-plugin-uni/commands/build.js @@ -1,4 +1,5 @@ const path = require('path') +const webpack = require('webpack') const { runByHBuilderX, @@ -73,7 +74,7 @@ module.exports = (api, options) => { process.env.VUE_CLI_BUILD_TARGET = args.target - if (args['sourcemap']) process.env.SOURCEMAP = args['sourcemap'] + if (args.sourcemap) process.env.SOURCEMAP = args.sourcemap await build(args, api, options) @@ -98,14 +99,18 @@ function getWebpackConfig (api, args, options) { if (args.minimize && process.env.NODE_ENV !== 'production') { modifyConfig(webpackConfig, config => { config.optimization.minimize = true - config.optimization.namedModules = false + if (webpack.version[0] <= 4) { + config.optimization.namedModules = false + } }) } else { modifyConfig(webpackConfig, config => { if (!config.optimization) { config.optimization = {} } - config.optimization.namedModules = false + if (webpack.version[0] <= 4) { + config.optimization.namedModules = false + } }) } return webpackConfig @@ -131,7 +136,6 @@ function getWebpackConfigs (api, args, options) { async function build (args, api, options) { const fs = require('fs-extra') const chalk = require('chalk') - const webpack = require('webpack') const { log, diff --git a/packages/vue-cli-plugin-uni/commands/serve.js b/packages/vue-cli-plugin-uni/commands/serve.js index 3a2d36d560236efa59c48d44a9f9bf0d5c571276..7bd7f4b14ea3504a8d199e81105e662b7a2d52b1 100644 --- a/packages/vue-cli-plugin-uni/commands/serve.js +++ b/packages/vue-cli-plugin-uni/commands/serve.js @@ -37,7 +37,7 @@ module.exports = (api, options) => { const url = require('url') const path = require('path') - const chalk = require('chalk') + const { chalk } = require('@vue/cli-shared-utils') const webpack = require('webpack') const WebpackDevServer = require('webpack-dev-server') const portfinder = require('portfinder') @@ -139,48 +139,98 @@ module.exports = (api, options) => { const compiler = webpack(webpackConfig) // create server - const server = new WebpackDevServer(compiler, Object.assign({ - clientLogLevel: 'none', - historyApiFallback: { - disableDotRule: true, - rewrites: [{ - from: /./, - to: path.posix.join(options.publicPath, 'index.html') - }] - }, - contentBase: api.resolve('public'), - watchContentBase: !isProduction, - hot: !isProduction, - quiet: true, - compress: isProduction, - publicPath: options.publicPath, - overlay: isProduction // TODO disable this - ? false : { - warnings: false, - errors: true + let server + if (webpack.version[0] > 4) { + server = new WebpackDevServer(Object.assign({ + historyApiFallback: { + disableDotRule: true, + rewrites: [{ + from: /./, + to: path.posix.join(options.publicPath, 'index.html') + }] + }, + hot: !isProduction, + compress: isProduction, + static: { + directory: api.resolve('public'), + publicPath: options.publicPath, + watch: !isProduction, + ...projectDevServerOptions.static + }, + client: { + logging: 'none', + overlay: isProduction // TODO disable this + ? false + : { warnings: false, errors: true }, + progress: !process.env.VUE_CLI_TEST, + ...projectDevServerOptions.client } - }, projectDevServerOptions, { - https: useHttps, - proxy: proxySettings, - before (app, server) { + }, projectDevServerOptions, { + https: useHttps, + proxy: proxySettings, + setupMiddlewares (middlewares, devServer) { + // launch editor support. + // this works with vue-devtools & @vue/cli-overlay + devServer.app.use('/__open-in-editor', launchEditorMiddleware(() => console.log( + 'To specify an editor, specify the EDITOR env variable or ' + + 'add "editor" field to your Vue project config.\n' + ))) + + // allow other plugins to register middlewares, e.g. PWA + // todo: migrate to the new API interface + api.service.devServerConfigFns.forEach(fn => fn(devServer.app, devServer)) + + if (projectDevServerOptions.setupMiddlewares) { + return projectDevServerOptions.setupMiddlewares(middlewares, devServer) + } + + return middlewares + } + }), compiler) + } else { + server = new WebpackDevServer(compiler, Object.assign({ + clientLogLevel: 'none', + historyApiFallback: { + disableDotRule: true, + rewrites: [{ + from: /./, + to: path.posix.join(options.publicPath, 'index.html') + }] + }, + contentBase: api.resolve('public'), + watchContentBase: !isProduction, + hot: !isProduction, + quiet: true, + compress: isProduction, + publicPath: options.publicPath, + overlay: isProduction // TODO disable this + ? false : { + warnings: false, + errors: true + } + }, projectDevServerOptions, { + https: useHttps, + proxy: proxySettings, + before (app, server) { // launch editor support. // this works with vue-devtools & @vue/cli-overlay - app.use('/__open-in-editor', launchEditorMiddleware(() => console.log( - 'To specify an editor, sepcify the EDITOR env variable or ' + + app.use('/__open-in-editor', launchEditorMiddleware(() => console.log( + 'To specify an editor, sepcify the EDITOR env variable or ' + 'add "editor" field to your Vue project config.\n' - ))) - // allow other plugins to register middlewares, e.g. PWA - api.service.devServerConfigFns.forEach(fn => fn(app, server)) - // apply in project middlewares - projectDevServerOptions.before && projectDevServerOptions.before(app, - server) - } - })) + ))) + // allow other plugins to register middlewares, e.g. PWA + api.service.devServerConfigFns.forEach(fn => fn(app, server)) + // apply in project middlewares + projectDevServerOptions.before && projectDevServerOptions.before(app, + server) + } + })) + } ; ['SIGINT', 'SIGTERM'].forEach(signal => { process.on(signal, () => { - server.close(() => { + server[webpack.version[0] > 4 ? 'stopCallback' : 'close'](() => { process.exit(0) }) }) @@ -192,7 +242,7 @@ module.exports = (api, options) => { process.stdin.on('data', data => { if (data.toString() === 'close') { console.log('got close signal!') - server.close(() => { + server[webpack.version[0] > 4 ? 'stopCallback' : 'close'](() => { process.exit(0) }) } @@ -303,11 +353,15 @@ module.exports = (api, options) => { server.showStatus = function () {} } - server.listen(port, host, err => { - if (err) { - reject(err) - } - }) + if (webpack.version[0] > 4) { + server.start().catch(err => reject(err)) + } else { + server.listen(port, host, err => { + if (err) { + reject(err) + } + }) + } }) }) } diff --git a/packages/vue-cli-plugin-uni/lib/app-plus/index.js b/packages/vue-cli-plugin-uni/lib/app-plus/index.js index 99193bbe04ace95defe0d9e74a7a4838e7c86464..88935bb52d3043667f7d6c279851986777b0edf4 100644 --- a/packages/vue-cli-plugin-uni/lib/app-plus/index.js +++ b/packages/vue-cli-plugin-uni/lib/app-plus/index.js @@ -70,7 +70,11 @@ const v3 = { webpackConfig.optimization = {} } // disable noEmitOnErrors - webpackConfig.optimization.noEmitOnErrors = false + if (webpack.version[0] > 4) { + webpackConfig.optimization.emitOnErrors = true + } else { + webpackConfig.optimization.noEmitOnErrors = false + } if (isAppService) { webpackConfig.optimization.runtimeChunk = { @@ -134,7 +138,8 @@ const v3 = { output: { filename: '[name].js', chunkFilename: '[id].js', - globalObject: 'this' + // webpack5 use strict + globalObject: webpack.version[0] > 4 ? '(new Function("return this")())' : 'this' }, performance: { hints: false @@ -158,7 +163,7 @@ const v3 = { compiler: vueLoader.compiler, before: [ beforeCode + require('../util').getAutomatorCode() + statCode + pushCode + uniCloudCode + - getGlobalUsingComponentsCode() + getGlobalUsingComponentsCode() ] } }] @@ -260,6 +265,8 @@ const v3 = { }) } + webpackConfig.plugin('vue-loader').use(require(vueLoader.loader).VueLoaderPlugin) + webpackConfig.plugins.delete('hmr') webpackConfig.plugins.delete('html') webpackConfig.plugins.delete('copy') diff --git a/packages/vue-cli-plugin-uni/lib/chain-webpack.js b/packages/vue-cli-plugin-uni/lib/chain-webpack.js index 038402d71f470348ffc9f05fdf368afc02c29064..b263aca74bafdfccafc5ac9b79dc1cf9e837e9bc 100644 --- a/packages/vue-cli-plugin-uni/lib/chain-webpack.js +++ b/packages/vue-cli-plugin-uni/lib/chain-webpack.js @@ -1,8 +1,5 @@ const path = require('path') - -const { - sassLoaderVersion -} = require('@dcloudio/uni-cli-shared/lib/scss') +const webpack = require('webpack') const { getPartialIdentifier @@ -23,11 +20,38 @@ module.exports = function chainWebpack (platformOptions, vueOptions, api) { const urlLoader = require('@dcloudio/uni-cli-shared/lib/url-loader') const staticTypes = ['images', 'media', 'fonts'] staticTypes.forEach(staticType => { - webpackConfig.module - .rule(staticType) - .use('url-loader') - .loader(urlLoader.loader) - .tap(options => Object.assign(options, urlLoader.options())) + const newOptions = urlLoader.options() + if (webpack.version[0] > 4) { + if ('limit' in newOptions) { + webpackConfig.module.rule(staticType).parser({ + dataUrlCondition: { + maxSize: newOptions.limit + } + }) + } + if (newOptions.fallback && newOptions.fallback.options) { + const generator = {} + const oldOptions = newOptions.fallback.options + const keys = ['publicPath', 'outputPath'] + keys.forEach(key => { + generator[key] = pathData => { + const outputPath = oldOptions.outputPath(null, pathData.module.request) + const basename = path.basename(outputPath) + return outputPath.substring(0, outputPath.length - basename.length) + } + }) + generator.filename = pathData => { + return path.basename(pathData.module.request) + } + webpackConfig.module.rule(staticType).set('generator', generator) + } + } else { + webpackConfig.module + .rule(staticType) + .use('url-loader') + .loader(urlLoader.loader) + .tap(options => Object.assign(options, newOptions)) + } }) // 条件编译 vue 文件统一直接过滤html,js,css三种类型,单独资源文件引用各自过滤 @@ -56,6 +80,18 @@ module.exports = function chainWebpack (platformOptions, vueOptions, api) { )) .before('css-loader') } + if (webpack.version[0] > 4) { + langRule.oneOf(type) + .use('css-loader') + .tap(options => { + options.url = { + filter: function (url) { + return url[0] !== '/' + } + } + return options + }) + } langRule.oneOf(type) .use('uniapp-preprocss') .loader(resolve('packages/webpack-preprocess-loader')) @@ -72,21 +108,19 @@ module.exports = function chainWebpack (platformOptions, vueOptions, api) { }) }) - if (sassLoaderVersion >= 8) { // check indentedSyntax - // vue cli 3 and sass-loader 8 - cssTypes.forEach(type => { - webpackConfig.module.rule('sass').oneOf(type).use('sass-loader').tap(options => { - if (options.indentedSyntax) { - if (!options.sassOptions) { - options.sassOptions = {} - } - options.sassOptions.indentedSyntax = true - delete options.indentedSyntax + // vue cli 3 and sass-loader 8 + cssTypes.forEach(type => { + webpackConfig.module.rule('sass').oneOf(type).use('sass-loader').tap(options => { + if (options.indentedSyntax) { + if (!options.sassOptions) { + options.sassOptions = {} } - return options - }) + options.sassOptions.indentedSyntax = true + delete options.indentedSyntax + } + return options }) - } + }) platformOptions.chainWebpack(webpackConfig, vueOptions, api) // define diff --git a/packages/vue-cli-plugin-uni/lib/commands/custom.js b/packages/vue-cli-plugin-uni/lib/commands/custom.js index 1718edb17aa13c3335497cc274cb75530792a848..f67c43d9d9848ba3472b9cedabce604dfdf1abf5 100644 --- a/packages/vue-cli-plugin-uni/lib/commands/custom.js +++ b/packages/vue-cli-plugin-uni/lib/commands/custom.js @@ -34,7 +34,7 @@ module.exports = function custom (argv) { clean: false, subpackage: argv.subpackage, plugin: argv.plugin, - sourcemap: argv['sourcemap'], + sourcemap: argv.sourcemap }).catch(err => { console.error(err) process.exit(1) diff --git a/packages/vue-cli-plugin-uni/lib/configure-webpack.js b/packages/vue-cli-plugin-uni/lib/configure-webpack.js index e49b473a44ac05a75fde62bf1fb73fb9cc726d9a..4011c1193eaaa909b7d355717e7e8098c0bee019 100644 --- a/packages/vue-cli-plugin-uni/lib/configure-webpack.js +++ b/packages/vue-cli-plugin-uni/lib/configure-webpack.js @@ -1,8 +1,8 @@ const fs = require('fs') const path = require('path') const webpack = require('webpack') -const RuleSet = require('webpack/lib/RuleSet') const CopyWebpackPlugin = require('copy-webpack-plugin') +const CopyWebpackPluginVersion = Number(require('copy-webpack-plugin/package.json').version.split('.')[0]) const merge = require('webpack-merge') @@ -39,12 +39,44 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt return (rule, i) => { const clone = Object.assign({}, rule) delete clone.include - const normalized = RuleSet.normalizeRule(clone, {}, '') - return ( - !rule.enforce && + if (webpack.version[0] > 4) { + const BasicEffectRulePlugin = require('webpack/lib/rules/BasicEffectRulePlugin') + const BasicMatcherRulePlugin = require('webpack/lib/rules/BasicMatcherRulePlugin') + const RuleSetCompiler = require('webpack/lib/rules/RuleSetCompiler') + const UseEffectRulePlugin = require('webpack/lib/rules/UseEffectRulePlugin') + const ruleSetCompiler = new RuleSetCompiler([ + new BasicMatcherRulePlugin('test', 'resource'), + new BasicMatcherRulePlugin('include', 'resource'), + new BasicMatcherRulePlugin('exclude', 'resource', true), + new BasicMatcherRulePlugin('resource'), + new BasicMatcherRulePlugin('conditions'), + new BasicMatcherRulePlugin('resourceQuery'), + new BasicMatcherRulePlugin('realResource'), + new BasicMatcherRulePlugin('issuer'), + new BasicMatcherRulePlugin('compiler'), + new BasicEffectRulePlugin('type'), + new BasicEffectRulePlugin('sideEffects'), + new BasicEffectRulePlugin('parser'), + new BasicEffectRulePlugin('resolve'), + new BasicEffectRulePlugin('generator'), + new UseEffectRulePlugin() + ]) + const ruleSet = ruleSetCompiler.compile([{ + rules: [clone] + }]) + const rules = ruleSet.exec({ + resource: fakeFile + }) + return rules.length > 0 && rule.use + } else { + const RuleSet = require('webpack/lib/RuleSet') + const normalized = RuleSet.normalizeRule(clone, {}, '') + return ( + !rule.enforce && normalized.resource && normalized.resource(fakeFile) - ) + ) + } } } @@ -152,13 +184,15 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt if (Array.isArray(uses)) { if (uses.find(use => babelLoaderRe.test(use.loader))) { const index = uses.findIndex(use => cacheLoaderRe.test(use.loader)) - if (process.env.UNI_USING_CACHE) { - Object.assign(uses[index].options, api.genCacheConfig( - 'babel-loader/' + process.env.UNI_PLATFORM, - getPartialIdentifier() - )) - } else { - uses.splice(index, 1) + if (index >= 0) { + if (process.env.UNI_USING_CACHE) { + Object.assign(uses[index].options, api.genCacheConfig( + 'babel-loader/' + process.env.UNI_PLATFORM, + getPartialIdentifier() + )) + } else { + uses.splice(index, 1) + } } } } @@ -198,12 +232,13 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt vueOptions.pluginOptions['uni-app-plus'].view if (!isAppView) { // app-plus view不需要copy - plugins.push(new CopyWebpackPlugin(getCopyWebpackPluginOptions(manifestPlatformOptions, vueOptions))) + const patterns = getCopyWebpackPluginOptions(manifestPlatformOptions, vueOptions) + plugins.push(new CopyWebpackPlugin(CopyWebpackPluginVersion > 5 ? { patterns } : patterns)) } if (!process.env.UNI_SUBPACKGE || !process.env.UNI_MP_PLUGIN) { try { const automatorJson = require.resolve('@dcloudio/uni-automator/dist/automator.json') - plugins.push(new CopyWebpackPlugin([{ + const patterns = [{ from: automatorJson, to: '../.automator/' + (process.env.UNI_SUB_PLATFORM || process.env.UNI_PLATFORM) + '/.automator.json', @@ -216,8 +251,9 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt } return '' } - }])) - } catch (e) {} + }] + plugins.push(new CopyWebpackPlugin(CopyWebpackPluginVersion > 5 ? { patterns } : patterns)) + } catch (e) { } } if (process.UNI_SCRIPT_ENV && Object.keys(process.UNI_SCRIPT_ENV).length) { @@ -289,8 +325,7 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt noSources: true, append: false } - if (isInHBuilderX && process.env.SOURCEMAP_PATH) - sourceMapOptions.filename = process.env.SOURCEMAP_PATH + if (isInHBuilderX && process.env.SOURCEMAP_PATH) { sourceMapOptions.filename = process.env.SOURCEMAP_PATH } if (useEvalSourceMap || useSourceMap) { plugins.push(sourceMap.createSourceMapDevToolPlugin(!sourceMapOptions.filename, sourceMapOptions)) } @@ -302,7 +337,7 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt } } } - + try { if (process.env.UNI_HBUILDERX_PLUGINS) { require(path.resolve(process.env.UNI_HBUILDERX_PLUGINS, 'uni_helpers/lib/bytenode')) diff --git a/packages/vue-cli-plugin-uni/lib/copy-webpack-options.js b/packages/vue-cli-plugin-uni/lib/copy-webpack-options.js index a38ce5e5ae42b482faa02e1bd378c042a423a6d7..514ef6d4b6b43b8272de8d547fdc4cf1e0790a87 100644 --- a/packages/vue-cli-plugin-uni/lib/copy-webpack-options.js +++ b/packages/vue-cli-plugin-uni/lib/copy-webpack-options.js @@ -7,6 +7,7 @@ const { initI18nOptions } = require('@dcloudio/uni-cli-shared/lib/i18n') const assetsDir = 'static' +const CopyWebpackPluginVersion = Number(require('copy-webpack-plugin/package.json').version.split('.')[0]) function getAssetsCopyOption (from, options = {}) { if (path.isAbsolute(from)) { @@ -42,7 +43,9 @@ function getAssetsCopyOptions (assetsDir) { const copyOptions = [] // 主包静态资源 - const mainAssetsCopyOption = getAssetsCopyOption(assetsDir, { + const mainAssetsCopyOption = getAssetsCopyOption(assetsDir, CopyWebpackPluginVersion > 5 ? { + globOptions: { ignore } + } : { ignore }) if (mainAssetsCopyOption) { @@ -51,11 +54,11 @@ function getAssetsCopyOptions (assetsDir) { // 分包静态资源 process.UNI_SUBPACKAGES && Object.keys(process.UNI_SUBPACKAGES).forEach(root => { - const subAssetsCopyOption = getAssetsCopyOption( - path.join(root, assetsDir), { - ignore - } - ) + const subAssetsCopyOption = getAssetsCopyOption(path.join(root, assetsDir), CopyWebpackPluginVersion > 5 ? { + globOptions: { ignore } + } : { + ignore + }) if (subAssetsCopyOption) { copyOptions.push(subAssetsCopyOption) } @@ -91,10 +94,8 @@ function getCopyWebpackPluginOptions (platformOptions, vueOptions) { if (process.env.UNI_PLATFORM === 'app-plus' && !process.env.UNI_AUTOMATOR_WS_ENDPOINT) { copyOptions.push({ from: path.resolve(process.env.UNI_INPUT_DIR, 'android*.json'), - to: '[name].[ext]', - globOptions: { - ignored: require('./util').getWatchOptions().ignored - }, + to: `[name]${CopyWebpackPluginVersion > 5 ? '' : '.'}[ext]`, + noErrorOnMissing: true, transform (content, path) { if (path.endsWith('androidPrivacy.json')) { const options = initI18nOptions( @@ -118,4 +119,4 @@ function getCopyWebpackPluginOptions (platformOptions, vueOptions) { module.exports = { assetsDir, getCopyWebpackPluginOptions -} +} diff --git a/packages/vue-cli-plugin-uni/lib/h5/cssnano-options.js b/packages/vue-cli-plugin-uni/lib/h5/cssnano-options.js index 5428a35896d8db2801ad35d8d65b6f9bb0eb6fe8..3324d8c8a6f6157e97cab34c1a4236a78c18c71f 100644 --- a/packages/vue-cli-plugin-uni/lib/h5/cssnano-options.js +++ b/packages/vue-cli-plugin-uni/lib/h5/cssnano-options.js @@ -1,15 +1,24 @@ const { getPlatformCssnano } = require('@dcloudio/uni-cli-shared') +const webpack = require('webpack') module.exports = function initCssnanoOptions (webpackConfig) { const module = webpackConfig.module // TODO 临时 hack calc:false 看看 vue cli 后续是否开放 cssnano 的配置 const cssnanoOptions = { - sourceMap: false, - plugins: [require('cssnano')({ - preset: ['default', getPlatformCssnano()] - })] + sourceMap: false + } + + const plugins = [require('cssnano')({ + preset: ['default', getPlatformCssnano()] + })] + + // TODO postcss-loader version > 4 + if (webpack.version[0] > 4) { + cssnanoOptions.postcssOptions = { plugins } + } else { + cssnanoOptions.plugins = plugins } module.rule('css').oneOf('vue-modules').use('cssnano').loader('postcss-loader').options(cssnanoOptions) diff --git a/packages/vue-cli-plugin-uni/lib/h5/index.js b/packages/vue-cli-plugin-uni/lib/h5/index.js index e6ec19eb19c5e1247e72298257b5fb7381c5de55..d0d621ba7dffdc612fb12583e6f201d6e0d26e47 100644 --- a/packages/vue-cli-plugin-uni/lib/h5/index.js +++ b/packages/vue-cli-plugin-uni/lib/h5/index.js @@ -160,9 +160,13 @@ module.exports = { }, plugins, optimization: { - moduleIds: 'hashed' + moduleIds: webpack.version[0] > 4 ? 'deterministic' : 'hashed' }, - devServer: { + devServer: webpack.version[0] > 4 ? { + watchFiles: { + options: require('../util').getWatchOptions() + } + } : { watchOptions: require('../util').getWatchOptions() } } diff --git a/packages/vue-cli-plugin-uni/lib/mp/index.js b/packages/vue-cli-plugin-uni/lib/mp/index.js index a88e10ca536ba6e2a4de6290db97c3682e54e56a..ffcb975d0833d8deb261a42cf73b9afb86c6904e 100644 --- a/packages/vue-cli-plugin-uni/lib/mp/index.js +++ b/packages/vue-cli-plugin-uni/lib/mp/index.js @@ -157,7 +157,11 @@ module.exports = { webpackConfig.optimization = {} } // disable noEmitOnErrors - webpackConfig.optimization.noEmitOnErrors = false + if (webpack.version[0] > 4) { + webpackConfig.optimization.emitOnErrors = true + } else { + webpackConfig.optimization.noEmitOnErrors = false + } webpackConfig.optimization.runtimeChunk = { name: 'common/runtime' @@ -300,23 +304,30 @@ ${globalEnv}.__webpack_require_UNI_MP_PLUGIN__ = __webpack_require__;` process.env.NODE_ENV === 'production' && process.env.UNI_PLATFORM !== 'app-plus' ) { - const OptimizeCssnanoPlugin = require('../../packages/@intervolga/optimize-cssnano-plugin/index.js') - webpackConfig.plugin('optimize-css') - .init((Plugin, args) => new OptimizeCssnanoPlugin({ - sourceMap: false, - filter (assetName) { - return path.extname(assetName) === styleExt - }, - cssnanoOptions: { - preset: [ - 'default', - Object.assign({}, getPlatformCssnano(), { - discardComments: true - }) - ] - } - - })) + // webpack5 不再使用 OptimizeCssnanoPlugin,改用 CssMinimizerPlugin + if (webpack.version[0] > 4) { + webpackConfig.optimization.minimizer('css').tap(args => { + args[0].test = new RegExp(`\\${styleExt}$`) + return args + }) + } else { + const OptimizeCssnanoPlugin = require('../../packages/@intervolga/optimize-cssnano-plugin/index.js') + webpackConfig.plugin('optimize-css') + .init((Plugin, args) => new OptimizeCssnanoPlugin({ + sourceMap: false, + filter (assetName) { + return path.extname(assetName) === styleExt + }, + cssnanoOptions: { + preset: [ + 'default', + Object.assign({}, getPlatformCssnano(), { + discardComments: true + }) + ] + } + })) + } } if (process.env.UNI_SUBPACKGE || process.env.UNI_MP_PLUGIN) { diff --git a/packages/vue-cli-plugin-uni/lib/options.js b/packages/vue-cli-plugin-uni/lib/options.js index 27cab09c1669bcf106567d4116024f8fca9a5a86..25ef468a8511efa098d2fb9a1798a46905ae2629 100644 --- a/packages/vue-cli-plugin-uni/lib/options.js +++ b/packages/vue-cli-plugin-uni/lib/options.js @@ -1,5 +1,6 @@ const fs = require('fs') const path = require('path') +const webpack = require('webpack') const isWin = /^win/.test(process.platform) @@ -23,11 +24,11 @@ module.exports = function initOptions (options) { options.transpileDependencies.push(genTranspileDepRegex(path.resolve(process.env.UNI_INPUT_DIR, 'node_modules'))) options.transpileDependencies.push('@dcloudio/uni-' + process.env.UNI_PLATFORM) options.transpileDependencies.push('@dcloudio/uni-i18n') - options.transpileDependencies.push('@dcloudio/uni-stat') + options.transpileDependencies.push('@dcloudio/uni-stat') options.transpileDependencies.push('@dcloudio/uni-push') options.transpileDependencies.push('@dcloudio/vue-cli-plugin-uni/packages/uni-app') options.transpileDependencies.push('@dcloudio/vue-cli-plugin-uni/packages/uni-cloud') - options.transpileDependencies.push('@dcloudio/vue-cli-plugin-uni/packages/uni-stat') + options.transpileDependencies.push('@dcloudio/vue-cli-plugin-uni/packages/uni-stat') options.transpileDependencies.push('@dcloudio/vue-cli-plugin-uni/packages/uni-push') if (process.env.UNI_PLATFORM !== 'mp-weixin') { // mp runtime @@ -59,8 +60,14 @@ module.exports = function initOptions (options) { options.css.loaderOptions.sass = {} } - if (!options.css.loaderOptions.postcss.config) { - options.css.loaderOptions.postcss.config = {} + if (webpack.version[0] > 4) { + if (!options.css.loaderOptions.postcss.postcssOptions) { + options.css.loaderOptions.postcss.postcssOptions = {} + } + } else { + if (!options.css.loaderOptions.postcss.config) { + options.css.loaderOptions.postcss.config = {} + } } // sass 全局变量 @@ -85,9 +92,10 @@ module.exports = function initOptions (options) { } options.css.loaderOptions.sass.prependData = sassData const userPostcssConfigPath = path.resolve(process.env.UNI_INPUT_DIR, 'postcss.config.js') - if (fs.existsSync(userPostcssConfigPath)) { - options.css.loaderOptions.postcss.config.path = userPostcssConfigPath + const configPath = fs.existsSync(userPostcssConfigPath) ? userPostcssConfigPath : path.resolve(process.env.UNI_CLI_CONTEXT, 'postcss.config.js') + if (webpack.version[0] > 4) { + options.css.loaderOptions.postcss.postcssOptions.config = configPath } else { - options.css.loaderOptions.postcss.config.path = path.resolve(process.env.UNI_CLI_CONTEXT, 'postcss.config.js') + options.css.loaderOptions.postcss.config.path = configPath } -} +} diff --git a/packages/vue-cli-plugin-uni/package.json b/packages/vue-cli-plugin-uni/package.json index 25c7c81a50f996637f374af09f5a358bd224d38d..421c0829cd3335d953121f1ac6fdf833fced7538 100644 --- a/packages/vue-cli-plugin-uni/package.json +++ b/packages/vue-cli-plugin-uni/package.json @@ -20,7 +20,6 @@ "@dcloudio/uni-stat": "^2.0.1-alpha-35420220804003", "buffer-json": "^2.0.0", "clone-deep": "^4.0.1", - "copy-webpack-plugin": "^5.1.1", "cross-env": "^5.2.0", "envinfo": "^6.0.1", "hash-sum": "^1.0.2", @@ -29,7 +28,6 @@ "mkdirp": "^0.5.1", "module-alias": "^2.1.0", "neo-async": "^2.6.1", - "postcss": "^7.0.7", "postcss-import": "^12.0.1", "postcss-selector-parser": "^5.0.0", "postcss-value-parser": "^3.3.1", @@ -39,5 +37,9 @@ "wrap-loader": "^0.2.0", "xregexp": "4.0.0" }, + "peerDependencies": { + "copy-webpack-plugin": ">=5", + "postcss": ">=7" + }, "gitHead": "4a974e44466ae58194372e446299cf83c7a3ad2c" } diff --git a/packages/vue-cli-plugin-uni/packages/app-vue-style-loader/index.js b/packages/vue-cli-plugin-uni/packages/app-vue-style-loader/index.js index 4adcd21964f4a442ae2eed0ec0743e48dd9d95ea..570ef3d29631456dc9d15a35811f99ff39fd816d 100644 --- a/packages/vue-cli-plugin-uni/packages/app-vue-style-loader/index.js +++ b/packages/vue-cli-plugin-uni/packages/app-vue-style-loader/index.js @@ -36,6 +36,8 @@ module.exports.pitch = function (remainingRequest) { '', '// load the styles', 'var content = require(' + request + ');', + // get default export if list is an ES Module (CSS Loader v4+) + "if(content.__esModule) content = content.default;", // content list format is [id, css, media, sourceMap] "if(typeof content === 'string') content = [[module.id, content, '']];", 'if(content.locals) module.exports = content.locals;' @@ -66,6 +68,7 @@ module.exports.pitch = function (remainingRequest) { ' if(!content.locals) {', ' module.hot.accept(' + request + ', function() {', ' var newContent = require(' + request + ');', + ' if(newContent.__esModule) newContent = newContent.default;', " if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];", ' update(newContent);', ' });', diff --git a/packages/vue-cli-plugin-uni/packages/h5-vue-style-loader/index.js b/packages/vue-cli-plugin-uni/packages/h5-vue-style-loader/index.js index 4adcd21964f4a442ae2eed0ec0743e48dd9d95ea..570ef3d29631456dc9d15a35811f99ff39fd816d 100644 --- a/packages/vue-cli-plugin-uni/packages/h5-vue-style-loader/index.js +++ b/packages/vue-cli-plugin-uni/packages/h5-vue-style-loader/index.js @@ -36,6 +36,8 @@ module.exports.pitch = function (remainingRequest) { '', '// load the styles', 'var content = require(' + request + ');', + // get default export if list is an ES Module (CSS Loader v4+) + "if(content.__esModule) content = content.default;", // content list format is [id, css, media, sourceMap] "if(typeof content === 'string') content = [[module.id, content, '']];", 'if(content.locals) module.exports = content.locals;' @@ -66,6 +68,7 @@ module.exports.pitch = function (remainingRequest) { ' if(!content.locals) {', ' module.hot.accept(' + request + ', function() {', ' var newContent = require(' + request + ');', + ' if(newContent.__esModule) newContent = newContent.default;', " if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];", ' update(newContent);', ' });', diff --git a/packages/vue-cli-plugin-uni/packages/postcss/index.js b/packages/vue-cli-plugin-uni/packages/postcss/index.js index 97521f9225e57db18e562e7e471539ae654fe029..a0da64cb66992a3f4c7d8cccc4d76a288ab2f0e1 100644 --- a/packages/vue-cli-plugin-uni/packages/postcss/index.js +++ b/packages/vue-cli-plugin-uni/packages/postcss/index.js @@ -156,7 +156,7 @@ if (process.env.UNI_USING_V3) { * 转换 upx * 转换 px */ - module.exports = postcss.plugin('postcss-uniapp-plugin', function (opts) { + const fn = function (opts) { opts = { ...defaultOpts, ...opts @@ -265,5 +265,20 @@ if (process.env.UNI_USING_V3) { }) } } - }) + } + + const version = Number(require('postcss/package.json').version.split('.')[0]) + + if (version < 8) { + module.exports = postcss.plugin('postcss-uniapp-plugin', fn) + } else { + module.exports = function (opts) { + return { + postcssPlugin: 'postcss-uniapp-plugin', + Once: fn(opts) + } + } + + module.exports.postcss = true + } } diff --git a/packages/vue-cli-plugin-uni/packages/postcss/index.v3.js b/packages/vue-cli-plugin-uni/packages/postcss/index.v3.js index 0e71bc9e97221bcc387a6029bc204467d7ead290..602d6bda9a656a78173242246f89781558233f5b 100644 --- a/packages/vue-cli-plugin-uni/packages/postcss/index.v3.js +++ b/packages/vue-cli-plugin-uni/packages/postcss/index.v3.js @@ -1,4 +1,3 @@ -const postcss = require('postcss') const selectorParser = require('postcss-selector-parser') const TAGS = Object.keys(require('@dcloudio/uni-cli-shared').tags) @@ -14,34 +13,50 @@ const isInsideKeyframes = function (rule) { let rewriteUrl -module.exports = postcss.plugin('postcss-uniapp-plugin', function (opts) { - return function (root, result) { - if (!rewriteUrl) { - rewriteUrl = require('@dcloudio/uni-cli-shared/lib/url-loader').rewriteUrl - } - rewriteUrl(root) - - root.walkRules(rule => { - // Transform each rule here - if (!isInsideKeyframes(rule)) { - // rule.selectors == comma seperated selectors - // a, b.c {} => ["a", "b.c"] - rule.selectors = rule.selectors.map(complexSelector => - // complexSelector => simpleSelectors - // "a.b#c" => ["a", ".b", "#c"] - transformSelector(complexSelector, simpleSelectors => { - // only process type selector, leave alone class & id selectors - return simpleSelectors.walkTags(tag => { - if (tag.value === 'page') { - tag.value = 'body' - } else if (~TAGS.indexOf(tag.value) && tag.value.substring( - 0, 4) !== 'uni-') { - tag.value = 'uni-' + tag.value - } - }) +function once (root) { + if (!rewriteUrl) { + rewriteUrl = require('@dcloudio/uni-cli-shared/lib/url-loader').rewriteUrl + } + rewriteUrl(root) + + root.walkRules(rule => { + // Transform each rule here + if (!isInsideKeyframes(rule)) { + // rule.selectors == comma seperated selectors + // a, b.c {} => ["a", "b.c"] + rule.selectors = rule.selectors.map(complexSelector => + // complexSelector => simpleSelectors + // "a.b#c" => ["a", ".b", "#c"] + transformSelector(complexSelector, simpleSelectors => { + // only process type selector, leave alone class & id selectors + return simpleSelectors.walkTags(tag => { + if (tag.value === 'page') { + tag.value = 'body' + } else if (~TAGS.indexOf(tag.value) && tag.value.substring( + 0, 4) !== 'uni-') { + tag.value = 'uni-' + tag.value + } }) - ) - } - }) + }) + ) + } + }) +} + +const version = Number(require('postcss/package.json').version.split('.')[0]) + +if (version < 8) { + const postcss = require('postcss') + module.exports = postcss.plugin('postcss-uniapp-plugin', function (opts) { + return once + }) +} else { + module.exports = function (opts) { + return { + postcssPlugin: 'postcss-uniapp-plugin', + Once: once + } } -}) + + module.exports.postcss = true +} diff --git a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.js b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.js index d3cdc9f3ba3300ab3d6cfd7ce5c7781cd8a8bc2e..83101617c2ccb48ac1ab0385e7f4651a28de784e 100644 --- a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.js +++ b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/index.js @@ -49,7 +49,7 @@ module.exports = function (source) { sourceMap, rootContext, resourcePath, - resourceQuery + resourceQuery = '' } = loaderContext const rawQuery = resourceQuery.slice(1) @@ -79,20 +79,20 @@ module.exports = function (source) { const isWin = /^win/.test(process.platform) const normalizePath = path => (isWin ? path.replace(/\\/g, '/') : path) - if(!options.compilerOptions){ + if (!options.compilerOptions) { options.compilerOptions = {} } options.compilerOptions.autoComponentResourcePath = normalizePath(resourcePath) // fixed by xxxxxx - if(!modules && options.compilerOptions && options.compilerOptions.modules){ - modules = options.compilerOptions.modules + if (!modules && options.compilerOptions && options.compilerOptions.modules) { + modules = options.compilerOptions.modules } const sourcePath = normalizePath(require('@dcloudio/uni-h5/path').src) if (normalizePath(this.resourcePath).indexOf(sourcePath) === 0) { descriptor.styles.length = 0 options.compilerOptions && (delete options.compilerOptions.modules) - } else if(options.compilerOptions){ + } else if (options.compilerOptions) { options.compilerOptions.modules = modules } } @@ -118,7 +118,7 @@ module.exports = function (source) { const id = hash( isProduction - ? (shortFilePath + '\n' + source) + ? shortFilePath + '\n' + source.replace(/\r\n/g, '\n') : shortFilePath ) @@ -164,7 +164,7 @@ module.exports = function (source) { } let renderjsImport = `var renderjs` - if((options.isAppView || options.isH5) && descriptor.renderjs){ + if ((options.isAppView || options.isH5) && descriptor.renderjs) { const src = descriptor.renderjs.src || resourcePath const attrsQuery = attrsToQuery(descriptor.renderjs.attrs, 'js') const query = `?vue&type=renderjs${attrsQuery}${inheritQuery}` @@ -205,7 +205,7 @@ var component = normalizer( render, staticRenderFns, ${hasFunctional ? `true` : `false`}, - ${options.isAppNVue ? `null`: (/injectStyles/.test(stylesCode) ? `injectStyles` : `null`)}, + ${options.isAppNVue ? `null` : (/injectStyles/.test(stylesCode) ? `injectStyles` : `null`)}, ${hasScoped ? JSON.stringify(id) : `null`}, ${isServer ? JSON.stringify(hash(request)) : `null`}, ${isShadow ? `true` : `false`}, @@ -228,7 +228,7 @@ var component = normalizer( } // fixed by xxxxxx (app-nvue injectStyles) if (options.isAppNVue && /injectStyles/.test(stylesCode)) { - code +=`\ninjectStyles.call(component)` + code += `\ninjectStyles.call(component)` } // Expose filename. This is used by the devtools and Vue runtime warnings. if (!isProduction) { @@ -236,7 +236,7 @@ var component = normalizer( // from the devtools. code += `\ncomponent.options.__file = ${JSON.stringify(rawShortFilePath.replace(/\\/g, '/'))}` } else if (options.exposeFilename) { - // Libraies can opt-in to expose their components' filenames in production builds. + // Libraries can opt-in to expose their components' filenames in production builds. // For security reasons, only expose the file's basename in production. code += `\ncomponent.options.__file = ${JSON.stringify(filename)}` } @@ -244,7 +244,6 @@ var component = normalizer( code += `\nrecyclableRender && (component.options["@render"] = recyclableRender)` // fixed by xxxxxx } code += `\nexport default component.exports` - // console.log(code) return code } diff --git a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin-webpack5.js b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin-webpack5.js index a3ec14dff3d016ca5b6a5960f7703d176a39f58a..bdb21a0ca4f69d759e59730c39d9f0b018988b2b 100644 --- a/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin-webpack5.js +++ b/packages/vue-cli-plugin-uni/packages/vue-loader/lib/plugin-webpack5.js @@ -6,28 +6,48 @@ const BasicMatcherRulePlugin = require('webpack/lib/rules/BasicMatcherRulePlugin const RuleSetCompiler = require('webpack/lib/rules/RuleSetCompiler') const UseEffectRulePlugin = require('webpack/lib/rules/UseEffectRulePlugin') +const objectMatcherRulePlugins = [] +try { + const ObjectMatcherRulePlugin = require('webpack/lib/rules/ObjectMatcherRulePlugin') + objectMatcherRulePlugins.push( + new ObjectMatcherRulePlugin('assert', 'assertions'), + new ObjectMatcherRulePlugin('descriptionData') + ) +} catch (e) { + const DescriptionDataMatcherRulePlugin = require('webpack/lib/rules/DescriptionDataMatcherRulePlugin') + objectMatcherRulePlugins.push(new DescriptionDataMatcherRulePlugin()) +} + const ruleSetCompiler = new RuleSetCompiler([ new BasicMatcherRulePlugin('test', 'resource'), + new BasicMatcherRulePlugin('mimetype'), + new BasicMatcherRulePlugin('dependency'), new BasicMatcherRulePlugin('include', 'resource'), new BasicMatcherRulePlugin('exclude', 'resource', true), - new BasicMatcherRulePlugin('resource'), new BasicMatcherRulePlugin('conditions'), + new BasicMatcherRulePlugin('resource'), new BasicMatcherRulePlugin('resourceQuery'), + new BasicMatcherRulePlugin('resourceFragment'), new BasicMatcherRulePlugin('realResource'), new BasicMatcherRulePlugin('issuer'), new BasicMatcherRulePlugin('compiler'), + ...objectMatcherRulePlugins, new BasicEffectRulePlugin('type'), new BasicEffectRulePlugin('sideEffects'), new BasicEffectRulePlugin('parser'), new BasicEffectRulePlugin('resolve'), + new BasicEffectRulePlugin('generator'), new UseEffectRulePlugin() ]) class VueLoaderPlugin { apply (compiler) { + const normalModule = compiler.webpack + ? compiler.webpack.NormalModule + : require('webpack/lib/NormalModule') // add NS marker so that the loader can detect and report missing plugin compiler.hooks.compilation.tap(id, compilation => { - const normalModuleLoader = require('webpack/lib/NormalModule').getCompilationHooks(compilation).loader + const normalModuleLoader = normalModule.getCompilationHooks(compilation).loader normalModuleLoader.tap(id, loaderContext => { loaderContext[NS] = true }) @@ -38,6 +58,10 @@ class VueLoaderPlugin { let vueRules = [] for (const rawRule of rules) { + // skip rules with 'enforce'. eg. rule for eslint-loader + if (rawRule.enforce) { + continue + } // skip the `include` check when locating the vue rule const clonedRawRule = Object.assign({}, rawRule) delete clonedRawRule.include @@ -71,7 +95,7 @@ class VueLoaderPlugin { ) } - // get the normlized "use" for vue files + // get the normalized "use" for vue files const vueUse = vueRules.filter(rule => rule.type === 'use').map(rule => rule.value) // get vue-loader options @@ -110,6 +134,7 @@ class VueLoaderPlugin { const pitcher = { loader: require.resolve('./loaders/pitcher'), resourceQuery: query => { + if (!query) { return false } const parsed = qs.parse(query.slice(1)) return parsed.vue != null }, @@ -128,8 +153,9 @@ class VueLoaderPlugin { } } +let uid = 0 function cloneRule (rawRule, refs) { - const rules = ruleSetCompiler.compileRules('ruleSet', [{ + const rules = ruleSetCompiler.compileRules(`clonedRuleSet-${++uid}`, [{ rules: [rawRule] }], refs) let currentResource @@ -182,6 +208,10 @@ function cloneRule (rawRule, refs) { delete res.test + if (rawRule.rules) { + res.rules = rawRule.rules.map(rule => cloneRule(rule, refs)) + } + if (rawRule.oneOf) { res.oneOf = rawRule.oneOf.map(rule => cloneRule(rule, refs)) } diff --git a/packages/webpack-uni-mp-loader/lib/babel/plugin-create-app.js b/packages/webpack-uni-mp-loader/lib/babel/plugin-create-app.js index c3fd3be6611900de9cc25b85a260b825294f0b4a..af41fdb267a6271c2a9c9ad5bd3d7a382ea54c27 100644 --- a/packages/webpack-uni-mp-loader/lib/babel/plugin-create-app.js +++ b/packages/webpack-uni-mp-loader/lib/babel/plugin-create-app.js @@ -5,6 +5,8 @@ module.exports = function ({ visitor: { MemberExpression (path, state) { if ( + // main.js main.ts + state.filename.startsWith(require('path').join(process.env.UNI_INPUT_DIR, 'main.')) && t.isIdentifier(path.node.property) && path.node.property.name === '$mount' && !path.node.$createApp diff --git a/packages/webpack-uni-mp-loader/lib/plugin/generate-component.js b/packages/webpack-uni-mp-loader/lib/plugin/generate-component.js index 667f256f55215e806b2ccd5f46a6c00bd60dfc2f..6502daed8d1d200059669f8857466857a7bc63f8 100644 --- a/packages/webpack-uni-mp-loader/lib/plugin/generate-component.js +++ b/packages/webpack-uni-mp-loader/lib/plugin/generate-component.js @@ -1,5 +1,6 @@ const fs = require('fs') const path = require('path') +const webpack = require('webpack') const { removeExt, normalizePath, @@ -121,8 +122,17 @@ module.exports = function generateComponent (compilation, jsonpFunction = 'webpa if (process.env.UNI_PLATFORM === 'mp-alipay') { beforeCode = ';my.defineComponent || (my.defineComponent = Component);' } - const source = beforeCode + origSource + - ` + const source = beforeCode + origSource + (webpack.version[0] > 4 + ? ` +;(${globalVar}["${jsonpFunction}"] = ${globalVar}["${jsonpFunction}"] || []).push([ + ['${chunkName}'], + {}, + function(__webpack_require__){ + __webpack_require__('${uniModuleId}')['createComponent'](__webpack_require__(${JSON.stringify(moduleId)})) + } +]); +` + : ` ;(${globalVar}["${jsonpFunction}"] = ${globalVar}["${jsonpFunction}"] || []).push([ '${chunkName}', { @@ -133,11 +143,18 @@ module.exports = function generateComponent (compilation, jsonpFunction = 'webpa [['${chunkName}']] ]); ` - const newSource = function () { - return source + ) + if (webpack.version[0] > 4) { + const { RawSource } = webpack.sources + const newSource = new RawSource(source) + compilation.updateAsset(name, newSource) + } else { + const newSource = function () { + return source + } + newSource.__$wrappered = true + assets[name].source = newSource } - newSource.__$wrappered = true - assets[name].source = newSource } } const styleExtname = getPlatformExts().style @@ -186,8 +203,14 @@ module.exports = function generateComponent (compilation, jsonpFunction = 'webpa }) delete sourceObj.componentGenerics const source = JSON.stringify(sourceObj, null, 2) - jsonFile.source = function () { - return source + if (webpack.version[0] > 4) { + const { RawSource } = webpack.sources + const newSource = new RawSource(source) + compilation.updateAsset(name, newSource) + } else { + jsonFile.source = function () { + return source + } } jsonFile.__$oldSource = oldSource } @@ -205,8 +228,14 @@ module.exports = function generateComponent (compilation, jsonpFunction = 'webpa }).join('') }) }) - templateFile.source = function () { - return templateSource + if (webpack.version[0] > 4) { + const { RawSource } = webpack.sources + const newSource = new RawSource(templateSource) + compilation.updateAsset(name, newSource) + } else { + templateFile.source = function () { + return templateSource + } } templateFile.__$oldSource = oldSource } @@ -215,15 +244,22 @@ module.exports = function generateComponent (compilation, jsonpFunction = 'webpa }) } // fix mp-qq https://github.com/dcloudio/uni-app/issues/2648 - const appJsonFile = compilation.assets['app.json'] + const appJsonName = 'app.json' + const appJsonFile = compilation.assets[appJsonName] if (process.env.UNI_PLATFORM === 'mp-qq' && appJsonFile) { const obj = JSON.parse(appJsonFile.source()) if (obj && obj.usingComponents && !Object.keys(obj.usingComponents).length) { const componentName = 'fix-2648' obj.usingComponents[componentName] = `/${componentName}` const source = JSON.stringify(obj, null, 2) - appJsonFile.source = function () { - return source + if (webpack.version[0] > 4) { + const { RawSource } = webpack.sources + const newSource = new RawSource(source) + compilation.updateAsset(appJsonName, newSource) + } else { + appJsonFile.source = function () { + return source + } } const files = [ { @@ -258,8 +294,14 @@ module.exports = function generateComponent (compilation, jsonpFunction = 'webpa const componentName = 'plugin-wrapper' obj.usingComponents[componentName] = `/${componentName}` const source = JSON.stringify(obj, null, 2) - appJsonFile.source = function () { - return source + if (webpack.version[0] > 4) { + const { RawSource } = webpack.sources + const newSource = new RawSource(source) + compilation.updateAsset(appJsonName, newSource) + } else { + appJsonFile.source = function () { + return source + } } const files = [ { diff --git a/packages/webpack-uni-mp-loader/lib/plugin/index-new.js b/packages/webpack-uni-mp-loader/lib/plugin/index-new.js index fdbcb3490df85dfc43f3261f2a12805e5c4e55a2..984597dd0ed61a9b84f03f7da739cb5f0ae123df 100644 --- a/packages/webpack-uni-mp-loader/lib/plugin/index-new.js +++ b/packages/webpack-uni-mp-loader/lib/plugin/index-new.js @@ -1,4 +1,5 @@ const path = require('path') +const webpack = require('webpack') const { md5, @@ -113,7 +114,7 @@ class WebpackUniMPPlugin { source }) => emitFile(file, source, compilation)) - generateComponent(compilation, compiler.options.output.jsonpFunction) + generateComponent(compilation, compiler.options.output[webpack.version[0] > 4 ? 'chunkLoadingGlobal' : 'jsonpFunction']) resolve() }) diff --git a/packages/webpack-uni-pages-loader/lib/platforms/mp-weixin/project.config.json b/packages/webpack-uni-pages-loader/lib/platforms/mp-weixin/project.config.json index cf89e6fdb232e45dd6a89cc69da690ce14a47c25..bee3774cd9f2297b173e81141fac7a3f6eb43d79 100644 --- a/packages/webpack-uni-pages-loader/lib/platforms/mp-weixin/project.config.json +++ b/packages/webpack-uni-pages-loader/lib/platforms/mp-weixin/project.config.json @@ -8,7 +8,8 @@ "es6": false, "postcss": false, "minified": false, - "newFeature": true + "newFeature": true, + "bigPackageSizeSupport": true }, "compileType": "miniprogram", "libVersion": "", diff --git a/packages/webpack-uni-pages-loader/lib/platforms/mp.js b/packages/webpack-uni-pages-loader/lib/platforms/mp.js index b47e4cae0e8029a22cc1479969a2ac5b6ff701d5..6a2250d11ef74b82ca759e086dc2c440f5302399 100644 --- a/packages/webpack-uni-pages-loader/lib/platforms/mp.js +++ b/packages/webpack-uni-pages-loader/lib/platforms/mp.js @@ -1,5 +1,6 @@ const fs = require('fs') const path = require('path') +const merge = require('merge') const { parsePages, @@ -30,6 +31,21 @@ function defaultCopy (name, value, json) { json[name] = value } +function isPlainObject (a) { + if (a === null) { + return false + } + return typeof a === 'object' +} + +function deepCopy (name, value, json) { + if (isPlainObject(value) && isPlainObject(json[name])) { + json[name] = merge.recursive(true, json[name], value) + } else { + defaultCopy(name, value, json) + } +} + const pagesJson2AppJson = { globalStyle: function (name, value, json) { json.window = parseStyle(value) @@ -115,7 +131,7 @@ const manifestJson2ProjectJson = { const platformJson2ProjectJson = { appid: defaultCopy, - setting: defaultCopy, + setting: deepCopy, miniprogramRoot: defaultCopy, cloudfunctionRoot: defaultCopy, qcloudRoot: defaultCopy, @@ -123,9 +139,9 @@ const platformJson2ProjectJson = { compileType: defaultCopy, libVersion: defaultCopy, projectname: defaultCopy, - packOptions: defaultCopy, - debugOptions: defaultCopy, - scripts: defaultCopy, + packOptions: deepCopy, + debugOptions: deepCopy, + scripts: deepCopy, cloudbaseRoot: defaultCopy }