first commit

This commit is contained in:
2026-09-08 20:28:54 +08:00
commit 2ada8d3d5a
37380 changed files with 4886169 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
'use strict'
module.exports = function (url, options) {
if (!options) {
// eslint-disable-next-line no-param-reassign
options = {}
} // eslint-disable-next-line no-underscore-dangle, no-param-reassign
url = url && url.__esModule ? url.default : url
var isAbsoluteFile = false
if (typeof url !== 'string') {
if (url.protocol && url.protocol === 'file:' && url.pathname) {
isAbsoluteFile = true
url = url.pathname
} else {
return url
}
} // If url is already wrapped in quotes, remove them
if (/^['"].*['"]$/.test(url)) {
// eslint-disable-next-line no-param-reassign
url = url.slice(1, -1)
}
if (options.hash) {
// eslint-disable-next-line no-param-reassign
url += options.hash
} // Should url be wrapped?
// See https://drafts.csswg.org/css-values-3/#urls
if (/["'() \t\n]/.test(url) || options.needQuotes) {
return '"'.concat(url.replace(/"/g, '\\"').replace(/\n/g, '\\n'), '"')
}
if (isAbsoluteFile) {
return url
}
if (url.indexOf('/') === 0) {
return url.substr(1)
}
return url
}
+296
View File
@@ -0,0 +1,296 @@
const path = require('path')
const webpack = require('webpack')
const {
getMainEntry,
getPlatformStat,
getPlatformPush,
getPlatformUniCloud,
getDevUniConsoleCode
} = require('@dcloudio/uni-cli-shared')
const vueLoader = require('@dcloudio/uni-cli-shared/lib/vue-loader')
const {
getGlobalUsingComponentsCode
} = require('@dcloudio/uni-cli-shared/lib/pages')
const WebpackUniAppPlugin = require('../../packages/webpack-uni-app-loader/plugin/index')
const {
getPartialIdentifier
} = require('../util')
// const {
// createTemplateCacheLoader
// } = require('../cache-loader')
const runtimePath = '@dcloudio/uni-mp-weixin/dist/mp.js'
const wxsPath = '@dcloudio/uni-mp-weixin/dist/wxs.js'
const uniCloudPath = path.resolve(__dirname, '../../packages/uni-cloud/dist/index.js')
const cryptoPath = path.resolve(__dirname, '../crypto.js')
function getProvides (isAppService) {
if (isAppService) {
return { // app-service
__f__: [path.resolve(__dirname, '../format-log.js'), 'default'],
wx: [runtimePath, 'default'],
'wx.nextTick': [runtimePath, 'nextTick'],
Page: [runtimePath, 'Page'],
Component: [runtimePath, 'Component'],
Behavior: [runtimePath, 'Behavior'],
getDate: [wxsPath, 'getDate'],
getRegExp: [wxsPath, 'getRegExp'],
uniCloud: [uniCloudPath, 'uniCloud'],
crypto: [cryptoPath, 'default'],
'window.crypto': [cryptoPath, 'default'],
'global.crypto': [cryptoPath, 'default']
}
}
return { // app-view
__f__: [path.resolve(__dirname, '../format-log.js'), 'default'],
getDate: [wxsPath, 'getDate'],
getRegExp: [wxsPath, 'getRegExp']
}
}
const v3 = {
vueConfig: {
parallel: false
},
webpackConfig (webpackConfig, vueOptions, api) {
const isAppService = !!vueOptions.pluginOptions['uni-app-plus'].service
const isAppView = !!vueOptions.pluginOptions['uni-app-plus'].view
const statCode = getPlatformStat()
const pushCode = getPlatformPush()
const uniCloudCode = getPlatformUniCloud()
const beforeCode = getDevUniConsoleCode() + 'import \'uni-pages\';'
if (!webpackConfig.optimization) {
webpackConfig.optimization = {}
}
// disable noEmitOnErrors
if (webpack.version[0] > 4) {
webpackConfig.optimization.emitOnErrors = true
} else {
webpackConfig.optimization.noEmitOnErrors = false
}
if (isAppService) {
webpackConfig.optimization.runtimeChunk = {
name: 'app-config'
}
webpackConfig.optimization.splitChunks = require('../split-chunks')()
} else if (isAppView) {
webpackConfig.optimization.runtimeChunk = false
webpackConfig.optimization.splitChunks = false
}
const rules = []
const scriptLoaders = []
if (isAppView) {
scriptLoaders.push({
loader: path.resolve(__dirname,
'../../packages/webpack-uni-app-loader/view/script')
})
}
scriptLoaders.push({
loader: path.resolve(__dirname,
'../../packages/webpack-uni-app-loader/using-components')
})
rules.push({ // 解析组件,css 等
resourceQuery: /vue&type=script/,
use: scriptLoaders
})
// TODO 临时方案,将 wxs 也编译至 service
rules.push({
resourceQuery: [/lang=wxs/, /blockType=wxs/],
use: [{
loader: path.resolve(__dirname, '../../packages/webpack-uni-filter-loader')
}]
})
if (isAppService) {
rules.push({
test: [/\.css$/, /\.p(ost)?css$/, /\.scss$/, /\.sass$/, /\.less$/, /\.styl(us)?$/],
use: [{
loader: path.resolve(__dirname, '../../packages/webpack-uni-app-loader/service/style.js')
}]
})
}
const entry = {}
if (isAppService) {
entry['app-service'] = path.resolve(process.env.UNI_INPUT_DIR, getMainEntry())
} else if (isAppView) {
entry['app-view'] = path.resolve(process.env.UNI_INPUT_DIR, getMainEntry())
}
const plugins = [
new WebpackUniAppPlugin(),
new webpack.ProvidePlugin(getProvides(isAppService))
]
if (isAppService) {
const {
WebpackUTSPlugin
} = require('@dcloudio/uni-cli-shared/lib/uts/uts-webpack-plugin.js')
plugins.push(new WebpackUTSPlugin())
}
return {
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
externals: {
vue: 'Vue'
},
entry () {
return entry
},
output: {
filename: '[name].js',
chunkFilename: '[id].js',
// webpack5 use strict
globalObject: webpack.version[0] > 4 ? '(new Function("return this")())' : 'this'
},
performance: {
hints: false
},
resolve: {
extensions: ['.nvue']
},
resolveLoader: {
alias: {
'vue-style-loader': path.resolve(__dirname, '../../packages/app-vue-style-loader')
}
},
module: {
rules: [{
test: path.resolve(process.env.UNI_INPUT_DIR, getMainEntry()),
use: [{
loader: isAppService
? path.resolve(__dirname, '../../packages/wrap-loader') : path.resolve(__dirname,
'../../packages/webpack-uni-app-loader/view/main.js'),
options: {
compiler: vueLoader.compiler,
before: [
beforeCode + require('../util').getAutomatorCode() + statCode + pushCode + uniCloudCode +
getGlobalUsingComponentsCode()
]
}
}]
},
{
resourceQuery: /vue&type=template/,
use: [{
loader: path.resolve(__dirname,
'../../packages/webpack-uni-app-loader/filter-modules-template.js')
}, {
loader: path.resolve(__dirname,
'../../packages/webpack-uni-app-loader/page-meta')
}]
},
{
type: 'javascript/auto',
resourceQuery: /uts-proxy/,
use: [{
loader: require.resolve('@dcloudio/uni-cli-shared/lib/uts/uts-loader.js')
}]
},
...rules
// v3 暂不支持 cache
// createTemplateCacheLoader(api,
// isAppService
// ? 'uni-template-compiler-service'
// : 'uni-template-compiler-view'
// )
]
},
plugins
}
},
chainWebpack (webpackConfig, vueOptions, api) {
webpackConfig.entryPoints.delete('app')
const isAppService = !!vueOptions.pluginOptions['uni-app-plus'].service
const isAppView = !!vueOptions.pluginOptions['uni-app-plus'].view
const cacheConfig = {
cacheDirectory: false,
cacheIdentifier: false
}
if (process.env.UNI_USING_CACHE) {
Object.assign(cacheConfig, api.genCacheConfig(
'vue-template-compiler/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
))
}
const compilerOptions = {
preserveWhitespace: false,
service: isAppService,
view: isAppView
}
// disable vue cache-loader
webpackConfig.module
.rule('vue')
.test(vueLoader.test)
.use('vue-loader') // service 层移除 style 节点,view 层返回固定 script
.loader(vueLoader.loader)
.tap(options => Object.assign(options, vueLoader.options({
isAppService,
isAppView
}, compilerOptions), cacheConfig))
.end()
// 是否启用 cache
if (process.env.UNI_USING_CACHE) {
webpackConfig.module
.rule('vue')
.use('cache-loader')
.tap(options => Object.assign(options, api.genCacheConfig(
'vue-loader/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
)))
} else {
webpackConfig.module
.rule('vue')
.uses
.delete('cache-loader')
}
if (isAppView) {
if (process.env.UNI_USING_V3_SCOPED) {
webpackConfig.module
.rule('vue')
.use('uniapp-app-style-scoped')
.loader(path.resolve(__dirname,
'../../packages/webpack-uni-app-loader/view/style'))
}
if (process.env.NODE_ENV === 'production') {
require('../h5/cssnano-options')(webpackConfig)
}
}
if (isAppService) { // service 层移除 css 相关
['css', 'postcss', 'scss', 'sass', 'less', 'stylus'].forEach(cssLang => {
webpackConfig.module.rules.delete(cssLang)
})
}
webpackConfig.plugin('vue-loader').use(require(vueLoader.loader).VueLoaderPlugin)
webpackConfig.plugins.delete('hmr')
webpackConfig.plugins.delete('html')
webpackConfig.plugins.delete('copy')
webpackConfig.plugins.delete('preload')
webpackConfig.plugins.delete('prefetch')
}
}
if (process.env.UNI_USING_V3) {
module.exports = v3
} else {
module.exports = require('../mp')
}
+81
View File
@@ -0,0 +1,81 @@
const fs = require('fs')
const path = require('path')
const mkdirp = require('mkdirp')
const BJSON = require('buffer-json')
const {
getPartialIdentifier
} = require('./util')
const directories = new Set()
function write (key, data, callback) {
const dirname = path.dirname(key)
// template,缓存 mp template
if (
data.remainingRequest.indexOf('vue&type=template') !== -1 &&
process.UNI_CACHE_TEMPLATES
) {
data.mpTemplates = process.UNI_CACHE_TEMPLATES
delete process.UNI_CACHE_TEMPLATES
}
const content = BJSON.stringify(data)
if (directories.has(dirname)) {
// for performance skip creating directory
fs.writeFile(key, content, 'utf-8', callback)
} else {
mkdirp(dirname, (mkdirErr) => {
if (mkdirErr) {
callback(mkdirErr)
return
}
directories.add(dirname)
fs.writeFile(key, content, 'utf-8', callback)
})
}
}
function read (key, callback) {
fs.readFile(key, 'utf-8', (err, content) => {
if (err) {
callback(err)
return
}
try {
const data = BJSON.parse(content)
const mpTemplates = data.mpTemplates
if (mpTemplates) {
Object.keys(mpTemplates).forEach(name => {
fs.writeFileSync(name, mpTemplates[name], 'utf-8')
})
}
callback(null, data)
} catch (e) {
callback(e)
}
})
}
module.exports = {
createTemplateCacheLoader: function (api, id = 'uni-template-compiler') {
return {
resourceQuery: /type=uni-cache-loader-template/,
use: [{
loader: 'cache-loader',
ident: 'uni-cache-loader-template-options',
options: Object.assign(api.genCacheConfig(
id + '/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
), {
read,
write
})
}]
}
}
}
+251
View File
@@ -0,0 +1,251 @@
const path = require('path')
const webpack = require('webpack')
const {
getPartialIdentifier
} = require('./util')
function resolve (dir) {
return path.resolve(__dirname, '..', dir)
}
module.exports = function chainWebpack (platformOptions, vueOptions, api) {
const {
runByHBuilderX, // 使用 HBuilderX 运行
cssPreprocessOptions
} = require('@dcloudio/uni-cli-shared')
return function (webpackConfig) {
// 处理静态资源 limit
const urlLoader = require('@dcloudio/uni-cli-shared/lib/url-loader')
const staticTypes = ['images', 'media', 'fonts']
staticTypes.forEach(staticType => {
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 options = newOptions.fallback.options
// const keys = ['publicPath', 'outputPath']
// keys.forEach(key => {
// generator[key] = pathData => {
// const outputPath = oldOptions[key](null, pathData.module.request)
// const basename = path.basename(outputPath)
// return outputPath.substring(0, outputPath.length - basename.length)
// }
// })
generator.filename = pathData => {
return options.name(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三种类型,单独资源文件引用各自过滤
const loaders = {
scss: 'sass-loader',
sass: 'sass-loader',
less: 'less-loader',
stylus: 'stylus-loader'
}
// 独立css,postcss,scss,sass,less,stylus
const cssLang = ['css', 'postcss', 'scss', 'sass', 'less', 'stylus']
const cssTypes = ['vue-modules', 'vue', 'normal-modules', 'normal']
cssLang.forEach(lang => {
const langRule = webpackConfig.module.rule(lang)
const loader = loaders[lang]
cssTypes.forEach(type => {
if (process.env.UNI_USING_CACHE) {
langRule.oneOf(type)
.use('uniapp-cache-css')
.loader('cache-loader')
.options(api.genCacheConfig(
'css-loader/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
))
.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
})
const platformExcludes = ['app-plus', 'h5', 'mp-360']
const platform = process.env.UNI_PLATFORM
if (!platformExcludes.includes(platform)) {
// remove warning https://github.com/vuejs/vue-loader/issues/1742
langRule.oneOf(type)
.use('extract-css-loader')
.tap(options => {
options.esModule = false
// 参考 https://github.com/vuejs/vue-cli/commit/b41ed76c5ce54c618587f24b9d14c35cf31a96d4
// 修复 部分平台 css 内的资源路径不正确,如uni-icons在百度小程序上引用的字体文件路径
options.publicPath = '/'
return options
})
}
} else {
if (langRule.oneOf(type).uses.has('extract-css-loader')) {
langRule.oneOf(type)
.use('extract-css-loader')
.tap(options => {
// 参考 https://github.com/vuejs/vue-cli/commit/b41ed76c5ce54c618587f24b9d14c35cf31a96d4
// 修复 部分平台 css 内的资源路径不正确,如uni-icons在百度小程序上引用的字体文件路径
if (options) options.publicPath = '/'
return options
})
}
}
langRule.oneOf(type)
.use('uniapp-preprocss')
.loader(resolve('packages/webpack-preprocess-loader'))
.options(cssPreprocessOptions)
.after('css-loader') // 在 css-loader 之前条件编译一次
if (loader) { // 在 scss,less,stylus 之前先条件编译一次(似乎没有必要了,保证css-loader处理一次即可,前提是条件编译注释都还存在)
langRule.oneOf(type)
.use('uniapp-preprocss-' + lang)
.loader(resolve('packages/webpack-preprocess-loader'))
.options(cssPreprocessOptions)
.after(loader)
}
})
})
// 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
}
return options
})
})
platformOptions.chainWebpack(webpackConfig, vueOptions, api)
// define
const deferredCreated = process.env.UNI_PLATFORM === 'mp-toutiao' ||
process.env.UNI_PLATFORM === 'quickapp-webview' ||
process.env.UNI_PLATFORM === 'mp-harmony'
const defines = {
// UNI_ENV好像没用
__UNI_FEATURE_PROMISE__: JSON.stringify(false),
'process.env.UNI_ENV': JSON.stringify(process.env.UNI_PLATFORM),
'process.env.UNI_APP_ID': JSON.stringify(process.env.UNI_APP_ID),
'process.env.UNI_APP_NAME': JSON.stringify(process.env.UNI_APP_NAME),
'process.env.UNI_PLATFORM': JSON.stringify(process.env.UNI_PLATFORM),
'process.env.UNI_SUB_PLATFORM': JSON.stringify(process.env.UNI_SUB_PLATFORM),
'process.env.UNI_CLOUD_PROVIDER': process.env.UNI_CLOUD_PROVIDER,
'process.env.UNI_SECURE_NETWORK_ENABLE': process.env.UNI_SECURE_NETWORK_ENABLE,
'process.env.UNI_SECURE_NETWORK_CONFIG': process.env.UNI_SECURE_NETWORK_CONFIG || '[]',
'process.env.UNICLOUD_DEBUG': process.env.UNICLOUD_DEBUG,
'process.env.RUN_BY_HBUILDERX': process.env.RUN_BY_HBUILDERX,
'process.env.UNI_AUTOMATOR_WS_ENDPOINT': JSON.stringify(process.env.UNI_AUTOMATOR_WS_ENDPOINT),
'process.env.UNI_STATISTICS_CONFIG': process.env.UNI_STATISTICS_CONFIG,
'process.env.UNI_STAT_UNI_CLOUD': process.env.UNI_STAT_UNI_CLOUD,
'process.env.UNI_STAT_DEBUG': process.env.UNI_STAT_DEBUG,
'process.env.UNI_COMPILER_VERSION': JSON.stringify(process.env.UNI_COMPILER_VERSION),
'process.env.UNI_APP_VERSION_NAME': JSON.stringify(process.env.UNI_APP_VERSION_NAME),
'process.env.UNI_APP_VERSION_CODE': JSON.stringify(process.env.UNI_APP_VERSION_CODE),
__UNI_SOCKET_HOSTS__: JSON.stringify(process.env.UNI_SOCKET_HOSTS || ''),
__UNI_SOCKET_PORT__: JSON.stringify(process.env.UNI_SOCKET_PORT || ''),
__UNI_SOCKET_ID__: JSON.stringify(process.env.UNI_SOCKET_ID || ''),
__UNI_CONSOLE_KEEP_ORIGINAL__: JSON.stringify(
!(process.env.UNI_PLATFORM === 'mp-harmony' ||
process.env.UNI_PLATFORM === 'app-harmony')
)
}
if (process.env.UNI_USING_VUE3) {
Object.assign(defines, {
__UNI_WX_API__: JSON.stringify(process.env.UNI_USING_WX_API === 'true'),
__UNI_WXS_API__: JSON.stringify(process.env.UNI_USING_WXS_API === 'true'),
__UNI_PROMISE_API__: JSON.stringify(process.env.UNI_USING_PROMISE_API === 'true'),
__VUE_OPTIONS_API__: JSON.stringify(process.env.UNI_USING_VUE3_OPTIONS_API === 'true'),
__VUE_CREATED_DEFERRED__: JSON.stringify(deferredCreated),
__VUE_PROD_DEVTOOLS__: JSON.stringify(false)
})
}
if (process.env.UNI_PLATFORM === 'h5') {
// TODO manifest.json
defines.__UNI_ROUTER_MODE__ = JSON.stringify('hash')
}
if (process.env.UNI_CLOUD_PROVIDER && process.env.NODE_ENV !== 'development') {
webpackConfig.optimization.minimizer('terser').tap((args) => {
// reduce_vars 优化常量
args[0].terserOptions.compress.reduce_vars = true
return args
})
}
webpackConfig
.plugin('uni-define')
.use(require.resolve('webpack/lib/DefinePlugin'), [defines])
if (runByHBuilderX) { // 由 HBuilderX 运行时,移除进度,错误
webpackConfig.plugins.delete('progress')
webpackConfig.plugins.delete('friendly-errors')
} else {
webpackConfig.plugin('friendly-errors')
.tap(args => {
if (global.__error_reporting__) {
args[0].onErrors = function (severity, errors) {
if (severity !== 'error') {
return
}
const error = errors[0]
global.__error_reporting__ && global.__error_reporting__(error.name, error.message || '')
}
}
return args
})
}
if (process.env.BUILD_ENV === 'ali-ide') {
webpackConfig.plugins.delete('progress')
}
// webpack4 support import mjs
if (webpack.version[0] < 5) {
webpackConfig.module
.rule('mjs')
.test(/.mjs$/)
.type('javascript/auto')
}
webpackConfig.resolve.alias
.delete('@')
.set(
'@/pages.json',
path.resolve(process.env.UNI_INPUT_DIR, 'pages.json') +
'?' + JSON.stringify({
type: 'origin-pages-json'
})
)
.set('@', path.resolve(process.env.UNI_INPUT_DIR))
}
}
File diff suppressed because one or more lines are too long
+42
View File
@@ -0,0 +1,42 @@
const path = require('path')
const Service = require('@vue/cli-service')
const {
initCustomScript
} = require('@dcloudio/uni-cli-shared/lib/package')
const uniI18n = require('@dcloudio/uni-cli-i18n')
module.exports = function custom (argv) {
const script = argv._[1]
if (!script) {
console.error(uniI18n.__('pluginUni.pleaseConfigScriptName'))
process.exit(0)
}
const scriptOptions = initCustomScript(script, path.resolve(process.cwd(), 'package.json'))
if (scriptOptions && scriptOptions.title) {
// console.log('>' + scriptOptions.title)
}
// @vue/cli-service/lib/Service.js
const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
const command = (
process.env.NODE_ENV === 'development' &&
process.env.UNI_PLATFORM === 'h5'
) ? 'uni-serve'
: 'uni-build'
service.run(command, {
watch: process.env.NODE_ENV === 'development',
minimize: process.env.UNI_MINIMIZE === 'true',
clean: false,
subpackage: argv.subpackage,
plugin: argv.plugin,
sourcemap: argv.sourcemap
}).catch(err => {
console.error(err)
process.exit(1)
})
}
+42
View File
@@ -0,0 +1,42 @@
const fs = require('fs')
const path = require('path')
const uniI18n = require('@dcloudio/uni-cli-i18n')
module.exports = async function add (argv) {
const pluginName = argv._[1]
if (!pluginName) {
console.error(uniI18n.__('pluginUni.pleaseSpecifyPluginName'))
process.exit(0)
}
const pluginPkg = require(pluginName + '/package.json')
const options = pluginPkg['uni-app']
if (!options) {
console.error(uniI18n.__('pluginUni.pluginIllegal'))
process.exit(0)
}
const name = options.name
if (!name) {
console.error(uniI18n.__('pluginUni.pluginNameNotExist'))
process.exit(0)
}
const scripts = options.scripts || {
['dev:' + name]: `cross-env NODE_ENV=development UNI_PLATFORM=${name} vue-cli-service uni-build --watch`,
['build:' + name]: `cross-env NODE_ENV=production UNI_PLATFORM=${name} vue-cli-service uni-build`
}
const pkgPath = path.resolve(process.cwd(), 'package.json')
const pkg = require(pkgPath)
if (!pkg.scripts) {
pkg.scripts = {}
}
let changed = false
Object.keys(scripts).forEach(script => {
if (!pkg.scripts[script]) {
changed = true
pkg.scripts[script] = scripts[script]
}
})
if (changed) {
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2))
}
}
+410
View File
@@ -0,0 +1,410 @@
const path = require('path')
const webpack = require('webpack')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const CopyWebpackPluginVersion = Number(require('copy-webpack-plugin/package.json').version.split('.')[0])
const merge = require('webpack-merge')
const {
getPartialIdentifier
} = require('./util')
function resolve (dir) {
return path.resolve(__dirname, '..', dir)
}
module.exports = function configureWebpack (platformOptions, manifestPlatformOptions, vueOptions, api) {
const {
runByHBuilderX, // 使用 HBuilderX 运行
isInHBuilderX, // 在 HBuilderX 的插件中
hasModule,
jsPreprocessOptions,
htmlPreprocessOptions,
uts
} = require('@dcloudio/uni-cli-shared')
const {
getPlatformVue
} = require('@dcloudio/uni-cli-shared/lib/platform')
const {
getCopyWebpackPluginOptions
} = require('./copy-webpack-options')
function createMatcher (fakeFile) {
return (rule, i) => {
const clone = Object.assign({}, rule)
delete clone.include
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)
)
}
}
}
function updateJsLoader (rawRules, fakeFile, checkLoaderRegex, loader) {
const matchRule = rawRules.find(createMatcher(fakeFile))
const matchUse = matchRule.use
const matchLoaderUseIndex = matchUse.findIndex(u => {
return checkLoaderRegex.test(u.loader)
})
if (matchLoaderUseIndex < 0) {
throw new Error(`No matching use for ${fakeFile}`)
}
matchUse.push(loader)
}
const tsLoaderOptions = require('./util').getTsLoadOptions()
function updateTsLoader (rawRules, fakeFile, loader, appendUTS = false) {
const matchRule = rawRules.find(createMatcher(fakeFile))
if (matchRule && matchRule.use) {
if (isInHBuilderX) {
matchRule.use.forEach(matchUse => {
if (matchUse.loader.includes('ts-loader')) {
Object.assign(matchUse.options, tsLoaderOptions)
if (appendUTS) {
if (!Array.isArray(matchUse.options.appendTsSuffixTo)) {
matchUse.options.appendTsSuffixTo = [matchUse.options.appendTsSuffixTo]
}
matchUse.options.appendTsSuffixTo.push(/\.uts$/)
}
}
})
}
if (appendUTS) {
if (!Array.isArray(matchRule.test)) {
matchRule.test = [matchRule.test]
}
matchRule.test.push(/\.uts$/)
}
matchRule.use.push(loader)
}
}
function removeForkTsCheckerWebpackPlugin (rawPlugins) {
if (isInHBuilderX && hasModule('fork-ts-checker-webpack-plugin')) {
const pluginIndex = rawPlugins.findIndex(rawPlugin => rawPlugin.vue && rawPlugin.typescriptVersion)
if (pluginIndex !== -1) {
// 移除fork-ts-checker-webpack-plugin
rawPlugins.splice(pluginIndex, 1)
// 恢复vue-loader的ts检查
tsLoaderOptions.transpileOnly = false
}
}
}
const babelLoaderRe = /^babel-loader|(\/|\\|@)babel-loader/
const cacheLoaderRe = /^cache-loader|(\/|\\|@)cache-loader/
return function (webpackConfig) {
// disable js cache-loader
const rawRules = webpackConfig.module.rules
for (let i = rawRules.length - 1; i >= 0; i--) {
const uses = rawRules[i].use
if (Array.isArray(uses)) {
const babelLoader = uses.find(use => babelLoaderRe.test(use.loader))
if (babelLoader) {
const options = api.genCacheConfig('babel-loader/' + process.env.UNI_PLATFORM, getPartialIdentifier())
if (webpack.version[0] > 4) {
babelLoader.options = babelLoader.options || {}
Object.assign(babelLoader.options, process.env.UNI_USING_CACHE ? options : {
cacheDirectory: false
})
} else {
const index = uses.findIndex(use => cacheLoaderRe.test(use.loader))
if (index >= 0) {
if (process.env.UNI_USING_CACHE) {
Object.assign(uses[index].options, options)
} else {
uses.splice(index, 1)
}
}
}
}
}
}
// 如果在 HBuilderX 中
removeForkTsCheckerWebpackPlugin(webpackConfig.plugins)
// js preprocess
updateJsLoader(rawRules, 'foo.js', babelLoaderRe, {
loader: resolve('packages/webpack-preprocess-loader'),
options: jsPreprocessOptions
})
// ts options and preprocess
updateTsLoader(rawRules, 'foo.ts', {
loader: resolve('packages/webpack-preprocess-loader'),
options: jsPreprocessOptions
}, true)
updateTsLoader(rawRules, 'foo.tsx', {
loader: resolve('packages/webpack-preprocess-loader'),
options: jsPreprocessOptions
})
let platformWebpackConfig = platformOptions.webpackConfig
if (typeof platformWebpackConfig === 'function') {
platformWebpackConfig = platformWebpackConfig(webpackConfig, vueOptions, api)
}
// 移除 node_modules 目录,避免受路径上的 node_modules 影响
if (require('@dcloudio/uni-cli-shared/lib/util').isInHBuilderX) {
webpackConfig.resolve.modules = webpackConfig.resolve.modules.filter(module => module !== 'node_modules')
}
const plugins = []
const isAppView = process.env.UNI_PLATFORM === 'app-plus' &&
vueOptions.pluginOptions &&
vueOptions.pluginOptions['uni-app-plus'] &&
vueOptions.pluginOptions['uni-app-plus'].view
if (!isAppView) { // app-plus view不需要copy
const patterns = getCopyWebpackPluginOptions(manifestPlatformOptions, vueOptions)
plugins.push(new CopyWebpackPlugin(CopyWebpackPluginVersion > 5 ? {
patterns
} : patterns))
const uniExtApis = require('@dcloudio/uni-cli-shared/lib/uts/uni_modules')
.parseUniExtApis(false, process.env.UNI_UTS_PLATFORM, 'javascript')
const keys = Object.keys(uniExtApis)
if (keys.length) {
const provides = {}
keys.forEach(name => {
const provide = uniExtApis[name]
if (Array.isArray(provide) && provide.length === 3) {
provide.pop()
}
provides[name] = provide
})
plugins.push(new webpack.ProvidePlugin(provides))
}
}
if (!process.env.UNI_SUBPACKGE || !process.env.UNI_MP_PLUGIN) {
try {
const automatorJson = require.resolve('@dcloudio/uni-automator/dist/automator.json')
const patterns = [{
from: automatorJson,
to: '../.automator/' + (process.env.UNI_SUB_PLATFORM || process.env.UNI_PLATFORM) +
'/.automator.json',
transform (content) {
if (process.env.UNI_AUTOMATOR_WS_ENDPOINT) {
return JSON.stringify({
version: require('@dcloudio/uni-automator/package.json').version,
wsEndpoint: process.env.UNI_AUTOMATOR_WS_ENDPOINT
})
}
return ''
}
}]
plugins.push(new CopyWebpackPlugin(CopyWebpackPluginVersion > 5 ? {
patterns
} : patterns))
} catch (e) {}
}
if (process.UNI_SCRIPT_ENV && Object.keys(process.UNI_SCRIPT_ENV).length) {
// custom define
const envs = Object.create(null)
Object.keys(process.UNI_SCRIPT_ENV).forEach(name => {
envs['process.env.' + name] = JSON.stringify(process.UNI_SCRIPT_ENV[name])
})
plugins.push(new webpack.DefinePlugin(envs))
}
if (runByHBuilderX) { // 使用 HBuilderX 中运行时,调整错误日志输出
const WebpackErrorsPlugin = require('../packages/webpack-errors-plugin')
const onErrors = require('../util/on-errors')
const onWarnings = require('../util/on-warnings')
plugins.push(new WebpackErrorsPlugin({
onErrors,
onWarnings
}))
}
const rules = [{
test: path.resolve(process.env.UNI_INPUT_DIR, 'pages.json'),
use: [{
loader: 'babel-loader'
}, {
loader: '@dcloudio/webpack-uni-pages-loader'
}],
type: 'javascript/auto'
},
{
resourceQuery: /vue&type=template/,
use: [{
loader: resolve('packages/webpack-preprocess-loader'),
options: htmlPreprocessOptions
}]
}
]
if (!process.env.UNI_USING_COMPONENTS) { // 新版本,在 script-loader 中处理(为了避免 babel generator 移除部分条件编译代码)
rules.push({
resourceQuery: /vue&type=script/,
use: [{
loader: resolve('packages/webpack-preprocess-loader'),
options: jsPreprocessOptions
}]
})
}
if (process.env.NODE_ENV === 'development' || (process.env.NODE_ENV === 'production' && process.env
.SOURCEMAP === 'true')) {
const sourceMap = require('@dcloudio/uni-cli-shared/lib/source-map')
let isAppService = false
if (
process.env.UNI_PLATFORM === 'app-plus' &&
vueOptions.pluginOptions &&
vueOptions.pluginOptions['uni-app-plus']
) {
isAppService = !!vueOptions.pluginOptions['uni-app-plus'].service
}
const useEvalSourceMap = process.env.UNI_PLATFORM === 'h5' || isAppService
const useSourceMap = process.env.UNI_PLATFORM.indexOf('mp-') === 0 &&
process.env.UNI_PLATFORM !== 'mp-baidu' &&
process.env.UNI_PLATFORM !== 'mp-alipay' &&
process.env.UNI_PLATFORM !== 'quickapp-webview' &&
process.env.UNI_PLATFORM !== 'mp-harmony' // 目前 ov 的开发工具支持 eval 模式
if (process.env.NODE_ENV === 'production') {
const sourceMapOptions = {
noSources: true,
append: false
}
if (isInHBuilderX && process.env.SOURCEMAP_PATH) {
sourceMapOptions.filename = process.env.SOURCEMAP_PATH
}
if (useEvalSourceMap || useSourceMap) {
plugins.push(sourceMap.createSourceMapDevToolPlugin(!sourceMapOptions.filename, sourceMapOptions))
}
} else {
if (useEvalSourceMap) {
plugins.push(sourceMap.createEvalSourceMapDevToolPlugin())
} else if (useSourceMap) {
plugins.push(sourceMap.createSourceMapDevToolPlugin(process.env.UNI_PLATFORM === 'mp-weixin' || process
.env.UNI_PLATFORM === 'mp-toutiao'))
}
}
}
try {
if (process.env.UNI_HBUILDERX_PLUGINS) {
require(path.resolve(process.env.UNI_HBUILDERX_PLUGINS, 'uni_helpers/lib/bytenode'))
const {
W
} = require(path.resolve(process.env.UNI_HBUILDERX_PLUGINS, 'uni_helpers'))
plugins.push(new W({
dir: process.env.UNI_INPUT_DIR
}))
}
} catch (e) {}
if (!runByHBuilderX && process.env.UNI_PLATFORM === 'mp-weixin') {
const { PreprocessorWebpackPlugin } = require('@dcloudio/uni-cli-shared/lib/preprocessor')
plugins.push(new PreprocessorWebpackPlugin())
}
const resolveLoaderAlias = {}
const modules = ['@vue/cli-plugin-babel', '@vue/cli-service']
modules.forEach(m => {
const {
dependencies
} = require(`${m}/package.json`)
Object.keys(dependencies).forEach(key => {
if (/-loader$/.test(key)) {
resolveLoaderAlias[key] = require.resolve(key)
}
})
})
const alias = {
'@': path.resolve(process.env.UNI_INPUT_DIR),
'./@': path.resolve(process.env
.UNI_INPUT_DIR), // css中的'@/static/logo.png'会被转换成'./@/static/logo.png'加载
vue$: getPlatformVue(vueOptions),
'uni-pages': path.resolve(process.env.UNI_INPUT_DIR, 'pages.json'),
'uni-stat-config': path.resolve(process.env.UNI_INPUT_DIR, 'pages.json') +
'?' +
JSON.stringify({
type: 'stat'
}),
vuex: require.resolve('@dcloudio/vue-cli-plugin-uni/packages/vuex3'),
'@vue/composition-api': require.resolve('@dcloudio/vue-cli-plugin-uni/packages/@vue/composition-api'),
'@dcloudio/uni-console': require.resolve('@dcloudio/vue-cli-plugin-uni/packages/uni-console/dist/index.esm.js')
}
if (process.env.UNI_PLATFORM.startsWith('mp')) {
const BabelRuntimeVersions = require('@babel/runtime/package.json').version.split('.')
if (BabelRuntimeVersions[0] === '7' && Number(BabelRuntimeVersions[1]) >= 18) {
alias['@babel/runtime/regenerator'] = require.resolve(
'@dcloudio/vue-cli-plugin-uni/packages/@babel/runtime/regenerator')
}
}
return merge({
devtool: false,
resolve: {
alias,
modules: [
process.env.UNI_INPUT_DIR,
path.resolve(process.env.UNI_INPUT_DIR, 'node_modules')
],
plugins: [
new uts.UTSResolverPlugin()
]
},
module: {
noParse: /^(vue|vue-router|vuex|vuex-router-sync)$/,
rules
},
resolveLoader: {
alias: resolveLoaderAlias
},
plugins,
performance: {
assetFilter (assetFilename) {
return !(/\.map$/.test(assetFilename)) && !(/vendor/.test(assetFilename))
}
},
watchOptions: require('./util').getWatchOptions()
}, platformWebpackConfig)
}
}
+177
View File
@@ -0,0 +1,177 @@
const fs = require('fs')
const path = require('path')
const {
compileI18nJsonStr
} = require('@dcloudio/uni-i18n')
const {
normalizePath
} = require('@dcloudio/uni-cli-shared')
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)) {
if (fs.existsSync(from)) {
return Object.assign({
from,
to: path.resolve(process.env.UNI_OUTPUT_DIR)
},
options
)
}
}
const to = from
from = path.resolve(process.env.UNI_INPUT_DIR, from)
if (fs.existsSync(from)) {
return Object.assign({
from,
to: path.resolve(process.env.UNI_OUTPUT_DIR, to)
},
options
)
}
}
function addIgnore (ignore, assetsDir, platform, ignoreStatic) {
if (CopyWebpackPluginVersion > 5) {
if (platform === 'app-plus') {
ignore.push(normalizePath(path.resolve(process.env.UNI_INPUT_DIR, assetsDir, 'app/**/*')))
} else if (platform === 'h5') {
ignore.push(normalizePath(path.resolve(process.env.UNI_INPUT_DIR, assetsDir, 'web/**/*')))
}
ignore.push(normalizePath(path.resolve(process.env.UNI_INPUT_DIR, assetsDir, platform + '/**/*')))
} else {
if (platform === 'app-plus') {
ignore.push('app/**/*')
} else if (platform === 'h5') {
ignore.push('web/**/*')
}
ignore.push(platform + '/**/*')
}
if (platform === 'app-plus') {
ignoreStatic.push(['static', 'app'])
} else if (platform === 'h5') {
ignoreStatic.push(['static', 'web'])
}
ignoreStatic.push(['static', platform])
}
let isIgnoreChecked = false
function checkIgnoreStatic (ignoreStatic) {
if (isIgnoreChecked) {
return
}
isIgnoreChecked = true
const existIgnore = new Set()
ignoreStatic.forEach(ignore => {
const dir = path.resolve(process.env.UNI_INPUT_DIR, ...ignore)
if (fs.existsSync(dir)) {
existIgnore.add(ignore.join('/'))
}
})
if (existIgnore.size) {
console.log('已忽略静态资源目录:' + [...existIgnore].join('、') +
'。详见:https://uniapp.dcloud.net.cn/tutorial/platform.html#static')
}
}
// 暂未考虑动态添加static目录
function getAssetsCopyOptions (assetsDir) {
const ignore = []
const ignoreStatic = []
global.uniPlugin.platforms.forEach(platform => {
if (global.uniPlugin.name !== platform) {
addIgnore(ignore, assetsDir, platform, ignoreStatic)
}
})
checkIgnoreStatic(ignoreStatic)
const copyOptions = []
// 主包静态资源
const mainAssetsCopyOption = getAssetsCopyOption(assetsDir, CopyWebpackPluginVersion > 5 ? {
noErrorOnMissing: true,
globOptions: {
ignore
}
} : {
ignore
})
if (mainAssetsCopyOption) {
copyOptions.push(mainAssetsCopyOption)
}
// 分包静态资源
process.UNI_SUBPACKAGES &&
Object.keys(process.UNI_SUBPACKAGES).forEach(root => {
const subAssetsCopyOption = getAssetsCopyOption(path.join(root, assetsDir), CopyWebpackPluginVersion > 5 ? {
noErrorOnMissing: true,
globOptions: {
ignore
}
} : {
ignore
})
if (subAssetsCopyOption) {
copyOptions.push(subAssetsCopyOption)
}
})
return copyOptions
}
function getUniModulesAssetsCopyOptions (assetsDir) {
const copyOptions = []
global.uniModules.forEach(module => {
copyOptions.push(
...getAssetsCopyOptions('uni_modules/' + module + '/' + assetsDir)
)
})
return copyOptions
}
function getCopyWebpackPluginOptions (platformOptions, vueOptions) {
const copyOptions = getAssetsCopyOptions(assetsDir).concat(
getUniModulesAssetsCopyOptions(assetsDir)
)
global.uniPlugin.copyWebpackOptions.forEach(copyWebpackOptions => {
const platformCopyOptions =
copyWebpackOptions(platformOptions, vueOptions, copyOptions) || []
platformCopyOptions.forEach(copyOption => {
if (typeof copyOption === 'string') {
copyOption = getAssetsCopyOption(copyOption)
}
copyOption && copyOptions.push(copyOption)
})
})
// 自动化测试时,不启用androidPrivacy.json
if (process.env.UNI_PLATFORM === 'app-plus' && !process.env.UNI_AUTOMATOR_WS_ENDPOINT) {
const fileName = 'androidPrivacy.json'
const context = path.resolve(process.env.UNI_INPUT_DIR)
if (fs.existsSync(path.join(context, fileName))) {
copyOptions.push({
from: fileName,
context,
to: fileName,
transform (content) {
const options = initI18nOptions(
process.env.UNI_PLATFORM,
process.env.UNI_INPUT_DIR,
false,
true
)
if (!options) {
return content
}
return compileI18nJsonStr(content.toString(), options)
}
})
}
}
return copyOptions
}
module.exports = {
assetsDir,
getCopyWebpackPluginOptions
}
+65
View File
@@ -0,0 +1,65 @@
var lookup = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 62, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 0, 0, 0, 0, 63, 0, 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
]
function base64Decode (source, target) {
var sourceLength = source.length
var paddingLength = (source[sourceLength - 2] === '=' ? 2 : (source[sourceLength - 1] === '=' ? 1
: 0))
var tmp
var byteIndex = 0
var baseLength = (sourceLength - paddingLength) & 0xfffffffc
for (var i = 0; i < baseLength; i += 4) {
tmp = (lookup[source.charCodeAt(i)] << 18) |
(lookup[source.charCodeAt(i + 1)] << 12) |
(lookup[source.charCodeAt(i + 2)] << 6) |
(lookup[source.charCodeAt(i + 3)])
target[byteIndex++] = (tmp >> 16) & 0xFF
target[byteIndex++] = (tmp >> 8) & 0xFF
target[byteIndex++] = (tmp) & 0xFF
}
if (paddingLength === 1) {
tmp = (lookup[source.charCodeAt(i)] << 10) |
(lookup[source.charCodeAt(i + 1)] << 4) |
(lookup[source.charCodeAt(i + 2)] >> 2)
target[byteIndex++] = (tmp >> 8) & 0xFF
target[byteIndex++] = tmp & 0xFF
}
if (paddingLength === 2) {
tmp = (lookup[source.charCodeAt(i)] << 2) | (lookup[source.charCodeAt(i + 1)] >> 4)
target[byteIndex++] = tmp & 0xFF
}
}
export default {
getRandomValues (arr) {
if (!(
arr instanceof Int8Array ||
arr instanceof Uint8Array ||
arr instanceof Int16Array ||
arr instanceof Uint16Array ||
arr instanceof Int32Array ||
arr instanceof Uint32Array ||
arr instanceof Uint8ClampedArray
)) {
throw new Error('Expected an integer array')
}
if (arr.byteLength > 65536) {
throw new Error('Can only request a maximum of 65536 bytes')
}
var crypto = uni.requireNativePlugin('DCloud-Crypto')
base64Decode(crypto.getRandomValues(arr.byteLength), new Uint8Array(arr.buffer, arr.byteOffset,
arr.byteLength))
return arr
}
}
+679
View File
@@ -0,0 +1,679 @@
const fs = require('fs')
const path = require('path')
const mkdirp = require('mkdirp')
const loaderUtils = require('loader-utils')
const uniI18n = require('@dcloudio/uni-cli-i18n')
const moduleAlias = require('module-alias')
require('./error-reporting')
require('../util/console')
const hasOwnProperty = Object.prototype.hasOwnProperty
function hasOwn (obj, key) {
return hasOwnProperty.call(obj, key)
}
// 输出编译器版本等信息
const pagesPkg = require('@dcloudio/webpack-uni-pages-loader/package.json')
process.env.UNI_COMPILER_VERSION = ''
if (pagesPkg) {
process.env.UNI_COMPILER_VERSION = pagesPkg['uni-app'].compilerVersion
}
const defaultInputDir = 'src'
if (process.env.UNI_INPUT_DIR && process.env.UNI_INPUT_DIR.indexOf('./') === 0) {
process.env.UNI_INPUT_DIR = path.resolve(process.cwd(), process.env.UNI_INPUT_DIR)
}
process.env.UNI_INPUT_DIR = process.env.UNI_INPUT_DIR || path.resolve(process.cwd(), defaultInputDir)
const {
getManifestJson,
isEnableUniPushV1,
isEnableUniPushV2,
isUniPushOffline,
hasPushModule,
isEnableSecureNetwork
} = require('@dcloudio/uni-cli-shared/lib/manifest')
const manifestJsonObj = getManifestJson()
process.env.UNI_APP_ID = manifestJsonObj.appid || ''
process.env.UNI_APP_NAME = manifestJsonObj.name || ''
process.env.UNI_PLATFORM = process.env.UNI_PLATFORM || 'h5'
process.env.UNI_APP_VERSION_NAME = manifestJsonObj.versionName
process.env.UNI_APP_VERSION_CODE = manifestJsonObj.versionCode
process.env.VUE_APP_DARK_MODE = (manifestJsonObj[process.env.UNI_PLATFORM] || {}).darkmode || false
// 如果配置了 dart-sass 或者是 Mac Arm 版本
const {
isInHBuilderX
} = require('@dcloudio/uni-cli-shared/lib/util')
if (isInHBuilderX) {
const isMacArm = process.platform === 'darwin' && process.arch === 'arm64'
if (isMacArm && manifestJsonObj.sassImplementationName === 'node-sass') {
console.warn('HBuilderX Mac Arm 版本 manifest.json->sassImplementationName 仅支持 dart-sass')
}
if (manifestJsonObj.sassImplementationName !== 'node-sass' || isMacArm) {
process.env.UNI_SASS_IMPLEMENTATION_NAME = 'dart-sass'
moduleAlias.addAlias('sass', path.resolve(process.env.UNI_HBUILDERX_PLUGINS,
'compile-dart-sass/node_modules/sass'))
}
}
// 小程序 vue3 标记
if (process.env.UNI_PLATFORM.indexOf('mp-') === 0) {
if (manifestJsonObj.vueVersion === '3' || manifestJsonObj.vueVersion === 3) {
process.env.UNI_USING_VUE3 = true
process.env.UNI_USING_VUE3_OPTIONS_API = true
}
}
// v2 uni-push
if (isEnableUniPushV2(manifestJsonObj, process.env.UNI_PLATFORM)) {
process.env.UNI_PUSH_V2 = true
if (process.env.UNI_PLATFORM === 'app-plus' && isUniPushOffline(manifestJsonObj)) {
process.env.UNI_PUSH_V2_OFFLINE = true
}
} else if (isEnableUniPushV1(manifestJsonObj, process.env.UNI_PLATFORM)) {
process.env.UNI_PUSH_V1 = true
}
if (hasPushModule(manifestJsonObj)) {
process.env.UNI_PUSH_MODULE = true
}
// 初始化全局插件对象
global.uniPlugin = require('@dcloudio/uni-cli-shared/lib/plugin').init()
const platformOptions = manifestJsonObj[process.env.UNI_SUB_PLATFORM || process.env.UNI_PLATFORM] || {}
// 插件校验环境
global.uniPlugin.validate.forEach(validate => {
validate(platformOptions, manifestJsonObj)
})
process.UNI_MANIFEST = manifestJsonObj
process.env.VUE_APP_NAME = manifestJsonObj.name
process.env.UNI_USING_V3_SCOPED = true
// 导出到小程序插件
process.env.UNI_MP_PLUGIN_EXPORT = JSON.stringify(Object.keys(platformOptions.plugins || {}).map(pluginName =>
platformOptions.plugins[pluginName].export))
const isH5 = !process.env.UNI_SUB_PLATFORM && process.env.UNI_PLATFORM === 'h5'
const isProduction = process.env.NODE_ENV === 'production'
// uniCloud
if (!process.env.UNI_CLOUD_PROVIDER && process.env.UNI_CLOUD_SPACES) {
process.env.UNI_CLOUD_PROVIDER = JSON.stringify([])
try {
const spaces = JSON.parse(process.env.UNI_CLOUD_SPACES)
if (Array.isArray(spaces)) {
const hasUniCloudSpace = spaces.length > 0
if (spaces.length === 1) {
const space = spaces[0]
console.log(uniI18n.__('pluginUni.currentProjectDefaultSpaceId', {
0: space.id
}))
}
if (
hasUniCloudSpace &&
isH5 &&
isProduction
) {
console.warn(uniI18n.__('pluginUni.unicloudReleaseH5', {
0: 'https://uniapp.dcloud.net.cn/uniCloud/publish.html#useinh5'
}))
} else if (
hasUniCloudSpace &&
isH5 &&
!isProduction
) {
console.warn(uniI18n.__('pluginUni.unicloudShowedRunByHBuilderX', {
0: 'https://uniapp.dcloud.net.cn/uniCloud/publish.html#useinh5'
}))
}
process.env.UNI_CLOUD_PROVIDER = JSON.stringify(spaces.map(space => {
if (space.provider === 'tcb') {
space.provider = 'tencent'
}
if (!space.provider && space.clientSecret) {
space.provider = 'aliyun'
}
switch (space.provider) {
case 'aliyun':
case 'dcloud':
return {
provider: space.provider || 'aliyun',
spaceName: space.name,
spaceId: space.id,
clientSecret: space.clientSecret,
endpoint: space.apiEndpoint
}
case 'alipay': {
return {
provider: space.provider,
spaceName: space.name,
spaceId: space.id,
spaceAppId: space.spaceAppId,
accessKey: space.accessKey,
secretKey: space.secretKey
}
}
case 'tencent':
default: {
return {
provider: space.provider,
spaceName: space.name,
spaceId: space.id
}
}
}
}))
}
} catch (e) {}
}
// 安全网络
process.env.UNI_SECURE_NETWORK_ENABLE = isEnableSecureNetwork(manifestJsonObj, process.env.UNI_PLATFORM)
// 初始化环境变量
process.env.UNI_CLI_CONTEXT = require('@dcloudio/uni-cli-shared/lib/util').getCLIContext()
const defaultOutputDir = './dist/' +
(process.env.NODE_ENV === 'production' ? 'build' : 'dev') + '/' +
(process.env.UNI_SUB_PLATFORM || process.env.UNI_PLATFORM)
process.env.UNI_OUTPUT_DEFAULT_DIR = path.resolve(process.env.UNI_CLI_CONTEXT, defaultOutputDir)
if (process.env.UNI_OUTPUT_DIR && process.env.UNI_OUTPUT_DIR.indexOf('./') === 0) {
process.env.UNI_OUTPUT_DIR = path.resolve(process.cwd(), process.env.UNI_OUTPUT_DIR)
}
process.env.UNI_PLATFORM = process.env.UNI_PLATFORM || 'h5'
process.env.VUE_APP_PLATFORM = process.env.UNI_PLATFORM
process.env.UNI_OUTPUT_DIR = process.env.UNI_OUTPUT_DIR || process.env.UNI_OUTPUT_DEFAULT_DIR
process.env.UNI_APP_X_TSC = 'true'
// if (manifestJsonObj['app-plus']?.['utsCompilerVersion'] === 'v1') {
// process.env.UNI_APP_X_TSC = 'false'
// }
const baseOutDir = path.basename(process.env.UNI_OUTPUT_DIR)
process.env.UNI_APP_X_CACHE_DIR =
process.env.UNI_APP_X_CACHE_DIR ||
path.resolve(process.env.UNI_OUTPUT_DIR, '../cache/.' + baseOutDir)
process.env.UNI_APP_X_TSC_DIR = path.resolve(
process.env.UNI_OUTPUT_DIR,
'../.tsc'
)
process.env.UNI_APP_X_UVUE_DIR = path.resolve(
process.env.UNI_OUTPUT_DIR,
'../.uvue'
)
process.env.UNI_APP_X_TSC_CACHE_DIR = path.resolve(
process.env.UNI_APP_X_CACHE_DIR,
'tsc'
)
initUtsPlatform()
function initUtsPlatform () {
if (process.env.UNI_APP_PLATFORM === 'android') {
process.env.UNI_UTS_PLATFORM = 'app-android'
}
if (process.env.UNI_APP_PLATFORM === 'ios') {
process.env.UNI_UTS_PLATFORM = 'app-ios'
}
if (process.env.UNI_PLATFORM === 'h5') {
process.env.UNI_UTS_PLATFORM = 'web'
} else {
if (!process.env.UNI_UTS_PLATFORM) {
process.env.UNI_UTS_PLATFORM = process.env.UNI_PLATFORM
}
}
process.env.UNI_UTS_TARGET_LANGUAGE = 'javascript'
if (process.env.UNI_UTS_PLATFORM === 'app-android') {
process.env.UNI_UTS_TARGET_LANGUAGE = 'kotlin'
} else if (process.env.UNI_UTS_PLATFORM === 'app-ios') {
process.env.UNI_UTS_TARGET_LANGUAGE = 'swift'
}
}
if (process.env.UNI_PLATFORM === 'app-plus') {
process.env.UNI_OUTPUT_TMP_DIR = path.resolve(process.env.UNI_OUTPUT_DIR, '../.tmp/app-plus')
}
process.UNI_LIBRARIES = process.UNI_LIBRARIES || ['@dcloudio/uni-ui']
if (process.env.NODE_ENV === 'production') { // 发行模式,不启用 cache
delete process.env.UNI_USING_CACHE
}
process.env.BROWSERSLIST_CONFIG = [
path.resolve(process.env.UNI_INPUT_DIR, '.browserslistrc'),
path.resolve(process.env.UNI_CLI_CONTEXT, 'package.json'),
path.resolve(process.cwd(), 'package.json')
].find(file => fs.existsSync(file))
const {
normalizePath,
isSupportSubPackages,
runByHBuilderX,
getPagesJson
} = require('@dcloudio/uni-cli-shared')
process.env.RUN_BY_HBUILDERX = JSON.stringify(runByHBuilderX)
const {
initUniModules
} = require('@dcloudio/uni-cli-shared/lib/uni_modules')
initUniModules()
const pagesJsonObj = getPagesJson()
// 读取分包
process.UNI_SUBPACKAGES = {}
if (Array.isArray(pagesJsonObj.subPackages)) {
pagesJsonObj.subPackages.forEach(subPackage => {
if (subPackage && subPackage.root) {
const {
name,
root,
independent
} = subPackage
process.UNI_SUBPACKAGES[root] = {
name,
root,
independent
}
}
})
}
process.UNI_PAGES = pagesJsonObj
if (manifestJsonObj.debug) {
process.env.VUE_APP_DEBUG = true
}
process.UNI_STAT_CONFIG = {
appid: manifestJsonObj.appid
}
// 默认启用 自定义组件模式
// if (isInHBuilderXAlpha) {
let usingComponentsAbsent = false
if (!hasOwn(platformOptions, 'usingComponents')) {
usingComponentsAbsent = true
}
platformOptions.usingComponents = true
// }
if (process.env.UNI_PLATFORM === 'h5') {
const optimization = platformOptions.optimization
if (optimization) {
// 发行模式且主动启用优化
const treeShaking = optimization.treeShaking
if (
treeShaking &&
treeShaking.enable &&
process.env.NODE_ENV === 'production'
) {
process.env.UNI_OPT_TREESHAKINGNG = true
process.UNI_USER_APIS = new Set()
if (Array.isArray(treeShaking.modules) && treeShaking.modules.length) {
const {
parseUserApis
} = require('@dcloudio/uni-cli-shared/lib/api')
try {
const modules = require('@dcloudio/uni-h5/lib/modules.json')
process.UNI_USER_APIS = parseUserApis(treeShaking.modules || [], modules)
} catch (e) {}
}
}
if (optimization.prefetch) {
process.env.UNI_OPT_PREFETCH = true
}
if (optimization.preload) {
process.env.UNI_OPT_PRELOAD = true
}
}
const indexCssBuffer = fs.readFileSync(require.resolve('@dcloudio/uni-h5/dist/index.css'))
process.env.VUE_APP_INDEX_CSS_HASH = loaderUtils.getHashDigest(indexCssBuffer, 'md5', 'hex', 8)
let indexDarkCssBuffer = ''
try {
indexDarkCssBuffer = fs.readFileSync(require.resolve('@dcloudio/uni-h5/dist/index.dark.css'))
process.env.VUE_APP_INDEX_DARK_CSS_HASH = loaderUtils.getHashDigest(indexDarkCssBuffer, 'md5', 'hex', 8)
} catch (error) {
process.env.VUE_APP_INDEX_DARK_CSS_HASH = ''
}
}
if (process.env.UNI_PLATFORM === 'mp-qq') { // QQ小程序 强制自定义组件模式
platformOptions.usingComponents = true
}
let isNVueCompiler = true
if (process.env.UNI_PLATFORM === 'app-plus') {
if (platformOptions.nvueCompiler === 'weex') {
isNVueCompiler = false
}
delete process.env.UNI_USING_CACHE
if (platformOptions.renderer === 'native') {
process.env.UNI_USING_V3_NATIVE = true
} else {
process.env.UNI_USING_V3 = true
platformOptions.usingComponents = true
}
process.env.UNI_OUTPUT_TMP_DIR = ''
// isNVueCompiler = true // v3 目前仅支持 uni-app 模式
// v3 支持指定 js 混淆(仅发行模式)
if (
process.env.NODE_ENV === 'production' &&
process.env.UNI_USING_V3
) {
const resources = platformOptions.confusion &&
platformOptions.confusion.resources
const resourcesKeys = resources &&
Object.keys(resources).filter(filepath => path.extname(filepath) === '.js')
if (resourcesKeys && resourcesKeys.length) {
process.UNI_CONFUSION = resourcesKeys.map(filepath =>
normalizePath(path.resolve(process.env.UNI_INPUT_DIR, filepath))
)
}
}
} else { // 其他平台,待确认配置方案
if (
manifestJsonObj['app-plus'] &&
manifestJsonObj['app-plus'].nvueCompiler === 'weex'
) {
isNVueCompiler = false
}
}
if (isNVueCompiler) {
process.env.UNI_USING_NVUE_COMPILER = true
}
if (platformOptions.nvueStyleCompiler === 'uni-app') {
process.env.UNI_USING_NVUE_STYLE_COMPILER = true
} else {
platformOptions.nvueStyleCompiler = 'weex'
}
if (platformOptions.usingComponents === true) {
if (process.env.UNI_PLATFORM !== 'h5') {
process.env.UNI_USING_COMPONENTS = true
}
if (process.env.UNI_PLATFORM === 'app-plus') {
process.env.UNI_USING_V8 = true
}
}
// 兼容历史配置 betterScopedSlots
const modes = ['legacy', 'auto', 'augmented']
const scopedSlotsCompiler = !platformOptions.scopedSlotsCompiler && platformOptions.betterScopedSlots ? modes[2]
: platformOptions.scopedSlotsCompiler
process.env.SCOPED_SLOTS_COMPILER = modes.includes(scopedSlotsCompiler) ? scopedSlotsCompiler : modes[1]
// 快手小程序、小红书小程序 抽象组件编译报错,如未指定 legacy 固定为 augmented 模式
if ((process.env.UNI_PLATFORM === 'mp-kuaishou' || process.env.UNI_PLATFORM === 'mp-xhs') && process.env
.SCOPED_SLOTS_COMPILER !== modes[0]) {
process.env.SCOPED_SLOTS_COMPILER = modes[2]
}
const slotMultipleInstance = !!platformOptions.slotMultipleInstance
// 配置 slotMultipleInstance 时,切换 scopedSlotsCompiler 的值 auto 为 augmented 模式
if (slotMultipleInstance && process.env.SCOPED_SLOTS_COMPILER === modes[1]) {
process.env.SCOPED_SLOTS_COMPILER = modes[2]
}
process.env.SLOT_MULTIPLE_INSTANCE = (slotMultipleInstance).toString()
process.env.MERGE_VIRTUAL_HOST_ATTRIBUTES = (!!platformOptions.mergeVirtualHostAttributes).toString()
process.env.UNI_STATISTICS_CONFIG = '""'
process.env.UNI_STAT_UNI_CLOUD = '""'
process.env.UNI_STAT_DEBUG = '""'
if (
process.env.UNI_USING_COMPONENTS ||
process.env.UNI_PLATFORM === 'h5'
) { // 自定义组件模式或 h5 平台
const uniStatistics = Object.assign(
manifestJsonObj.uniStatistics || {},
platformOptions.uniStatistics || {}
)
if (uniStatistics.enable === true) {
const uniStatLog = (text) => {
console.log()
console.warn(text)
console.log()
}
const version = Number(uniStatistics.version) === 2 ? '2' : '1'
process.env.UNI_USING_STAT = version
// 获取服务空间配置信息
const uniCloudConfig = uniStatistics.uniCloud || {}
process.env.UNI_STATISTICS_CONFIG = JSON.stringify(uniStatistics)
process.env.UNI_STAT_UNI_CLOUD = JSON.stringify(uniCloudConfig)
process.env.UNI_STAT_DEBUG = uniStatistics.debug === true ? 'true' : 'false'
if (process.env.NODE_ENV === 'production') {
if (!process.UNI_STAT_CONFIG.appid) {
uniStatLog(uniI18n.__('pluginUni.uniStatisticsNoAppid', {
0: 'https://ask.dcloud.net.cn/article/36303'
}))
} else {
if (!uniStatistics.version) {
uniStatLog(uniI18n.__('pluginUni.uniStatisticsNoVersion', {
0: 'https://uniapp.dcloud.io/uni-stat-v2.html'
}))
} else {
uniStatLog(`已开启 uni统计${uniStatistics.version}.0 版本`)
if (version === '2') {
uniStatLog(
'【重要】因 HBuilderX 3.4.9 版本起,uni统计2.0 调整了安卓端 deviceId 获取方式,导致 uni统计2.0 App-Android平台部分统计数据不准确。如使用了HBuilderX 3.4.9 - 3.6.4版本且开通了uni统计2.0的应用,需要使用HBuilderX3.6.7及以上版本重新发布应用并升级 uniAdmin 云函数解决,详见:https://ask.dcloud.net.cn/article/40097'
)
}
}
}
} else {
if (!uniStatistics.version) {
uniStatLog(uniI18n.__('pluginUni.uniStatisticsNoVersion', {
0: 'https://uniapp.dcloud.io/uni-stat-v2.html'
}))
} else {
uniStatLog(`已开启 uni统计${uniStatistics.version}.0 版本`)
if (version === '2') {
uniStatLog(
'【重要】因 HBuilderX 3.4.9 版本起,uni统计2.0 调整了安卓端 deviceId 获取方式,导致 uni统计2.0 App-Android平台部分统计数据不准确。如使用了HBuilderX 3.4.9 - 3.6.4版本且开通了uni统计2.0的应用,需要使用HBuilderX3.6.7及以上版本重新发布应用并升级 uniAdmin 云函数解决,详见:https://ask.dcloud.net.cn/article/40097'
)
}
}
}
}
}
if (process.env.UNI_USING_COMPONENTS) { // 是否启用分包优化
if (platformOptions.optimization) {
if (
isSupportSubPackages() &&
platformOptions.optimization.subPackages &&
Object.keys(process.UNI_SUBPACKAGES).length
) {
process.env.UNI_OPT_SUBPACKAGES = true
}
}
}
const warningMsg =
usingComponentsAbsent
? '该应用之前可能是非自定义组件模式,目前以自定义组件模式运行。非自定义组件已于2019年11月1日起停止支持。详见:https://ask.dcloud.net.cn/article/36385'
: 'uni-app已于2019年11月1日起停止支持非自定义组件模式 [详情](https://ask.dcloud.net.cn/article/36385)'
const needWarning = !platformOptions.usingComponents || usingComponentsAbsent
let hasNVue = false
const compileModeUrl = 'https://ask.dcloud.net.cn/article/36074'
if (process.env.UNI_USING_NATIVE || process.env.UNI_USING_V3_NATIVE) {
const compileMode = (process.env.UNI_USING_V3_NATIVE ? 'v3' : '') + '' + (isNVueCompiler ? 'uni-app' : 'weex')
console.log(uniI18n.__('pluginUni.nvueCompileModeForDetail', {
0: compileMode,
1: compileModeUrl
}))
} else if (process.env.UNI_PLATFORM !== 'h5' && process.env.UNI_PLATFORM !== 'quickapp-native') {
try {
const info = process.env.UNI_COMPILER_VERSION
if (process.env.UNI_PLATFORM === 'app-plus') {
if (process.env.UNI_USING_V3) {
console.log(info)
} else {
const glob = require('glob')
hasNVue = !!glob.sync('pages/**/*.nvue', {
cwd: process.env.UNI_INPUT_DIR
}).length
if (hasNVue) {
console.log(info)
if (needWarning) {
console.log(warningMsg)
}
console.log(uniI18n.__('pluginUni.nvueCompileModeForDetail', {
0: (isNVueCompiler ? 'uni-app' : 'weex'),
1: compileModeUrl
}))
} else {
console.log(info)
if (needWarning) {
console.log(warningMsg)
}
}
}
} else {
if (needWarning) {
console.log(warningMsg)
}
}
} catch (e) {}
}
if (process.env.NODE_ENV !== 'production') { // 运行模式性能提示
let perfMsg = uniI18n.__('pluginUni.runDebugMode')
if (hasNVue) { // app-nvue
perfMsg = perfMsg + uniI18n.__('pluginUni.runDebugModeNvue')
} else if (process.env.UNI_PLATFORM.indexOf('mp-') === 0) { // 小程序
perfMsg = perfMsg + uniI18n.__('pluginUni.runDebugModeMP')
}
console.log(perfMsg)
}
// 将 template-compiler 指向修订后的版本
moduleAlias.addAlias('vue-template-compiler', '@dcloudio/vue-cli-plugin-uni/packages/vue-template-compiler')
moduleAlias.addAlias('@megalo/template-compiler', '@dcloudio/vue-cli-plugin-uni/packages/@megalo/template-compiler')
moduleAlias.addAlias('mpvue-template-compiler', '@dcloudio/vue-cli-plugin-uni/packages/mpvue-template-compiler')
// vue-loader
moduleAlias.addAlias('vue-loader', '@dcloudio/vue-cli-plugin-uni/packages/vue-loader')
// sass-loader
moduleAlias.addAlias('sass-loader', '@dcloudio/vue-cli-plugin-uni/packages/sass-loader')
if (process.env.UNI_USING_V3 && process.env.UNI_PLATFORM === 'app-plus') {
moduleAlias.addAlias('./runtime/getUrl.js', '@dcloudio/vue-cli-plugin-uni/lib/app-plus/getUrl.js')
moduleAlias.addAlias('../runtime/getUrl.js', '@dcloudio/vue-cli-plugin-uni/lib/app-plus/getUrl.js')
moduleAlias.addAlias('vue-style-loader', '@dcloudio/vue-cli-plugin-uni/packages/app-vue-style-loader')
}
if (process.env.UNI_PLATFORM === 'h5') {
moduleAlias.addAlias('vue-style-loader', '@dcloudio/vue-cli-plugin-uni/packages/h5-vue-style-loader')
}
if (process.env.UNI_PLATFORM === 'mp-toutiao' || process.env.UNI_PLATFORM === 'mp-lark') {
// !important 始终带有一个空格
moduleAlias.addAlias(
'postcss-normalize-whitespace',
'@dcloudio/vue-cli-plugin-uni/packages/postcss-normalize-whitespace'
)
}
if (runByHBuilderX) {
const oldError = console.error
console.error = function (msg) {
if (typeof msg === 'string' && msg.includes(
'[BABEL] Note: The code generator has deoptimised the styling of')) {
const filePath = msg.replace('[BABEL] Note: The code generator has deoptimised the styling of ', '').split(
' as ')[0]
console.log('[' + uniI18n.__('warning') + '] `' + path.relative(process.env.UNI_INPUT_DIR, filePath) +
'` 文件体积超过 500KB,已跳过压缩以及 ES6 转 ES5 的处理,手机端使用过大的js库影响性能。')
} else {
oldError.apply(console, arguments)
// TODO 如果是首次运行遇到错误直接退出
}
}
}
if (
process.env.UNI_USING_CACHE &&
process.env.UNI_PLATFORM !== 'h5' &&
!process.env.UNI_USING_V3 &&
!process.env.UNI_USING_NATIVE &&
!process.env.UNI_USING_V3_NATIVE
) { // 使用 cache, 拷贝 cache 的 json
const cacheJsonDir = path.resolve(
process.env.UNI_CLI_CONTEXT,
'node_modules/.cache/uni-pages-loader/' + process.env.UNI_PLATFORM
)
if (!fs.existsSync(cacheJsonDir)) { // 创建 cache 目录
mkdirp(cacheJsonDir)
} else {
require('@dcloudio/uni-cli-shared/lib/cache').restore()
}
}
const {
initAutoImportComponents,
initAutoImportScanComponents
} = require('@dcloudio/uni-cli-shared/lib/pages')
process.UNI_AUTO_SCAN_COMPONENTS = !(pagesJsonObj.easycom && pagesJsonObj.easycom.autoscan === false)
initAutoImportComponents(pagesJsonObj.easycom)
if (process.UNI_AUTO_SCAN_COMPONENTS) {
initAutoImportScanComponents()
}
global.uniPlugin.configureEnv.forEach(configureEnv => {
configureEnv()
})
if (
process.env.UNI_PLATFORM === 'h5' ||
(
process.env.UNI_PLATFORM === 'app-plus' &&
process.env.UNI_USING_V3
)
) {
const migrate = require('@dcloudio/uni-migration')
const wxcomponentDirs = [path.resolve(process.env.UNI_INPUT_DIR, 'wxcomponents')]
global.uniModules.forEach(module => {
wxcomponentDirs.push(path.resolve(process.env.UNI_INPUT_DIR, 'uni_modules', module, 'wxcomponents'))
})
wxcomponentDirs.forEach(wxcomponentsDir => {
if (fs.existsSync(wxcomponentsDir)) { // 转换 mp-weixin 小程序组件
try {
migrate(wxcomponentsDir, false, {
silent: true // 不输出日志
})
} catch (err) {
console.warn(err)
}
}
})
}
if (process.env.UNI_PLATFORM.startsWith('mp-')) {
console.log(uniI18n.__('pluginUni.mpBrowserKernelDifference', {
0: 'https://uniapp.dcloud.io/matter?id=mp'
}))
}
runByHBuilderX && console.log(uniI18n.__('compiling'))
module.exports = {
manifestPlatformOptions: platformOptions
}
+162
View File
@@ -0,0 +1,162 @@
const {
pathToRegexp,
isInHBuilderX
} = require('@dcloudio/uni-cli-shared/lib/util')
const plp = require('@dcloudio/webpack-uni-pages-loader/package.json')
class ErrorReport {
static get instance () {
if (this._instance == null) {
this._instance = new ErrorReport()
}
return this._instance
}
constructor () {
this._instance = null
this._os = null
this._https = null
this._crypto = null
this._cacheList = []
this._UNI_INPUT_DIR_REG = pathToRegexp(process.env.UNI_INPUT_DIR, { global: true })
this._UNI_CLI_CONTEXT_REG = pathToRegexp(process.env.UNI_CLI_CONTEXT, { global: true })
}
get os () {
if (this._os == null) {
this._os = require('os')
}
return this._os
}
get https () {
if (this._https == null) {
this._https = require('https')
}
return this._https
}
report (type, err = '') {
if (!this._shouldReport(err)) {
return
}
if (typeof err === 'object') {
try {
err = err.toString()
} catch (e) {}
}
err = err.replace(this._UNI_INPUT_DIR_REG, 'UNI_INPUT_DIR')
err = err.replace(this._UNI_CLI_CONTEXT_REG, 'UNI_CLI_CONTEXT')
const data = JSON.stringify({
di: this._getMD5(this._getMac()),
np: process.platform,
nv: process.version,
cp: process.env.UNI_PLATFORM,
cv: plp['uni-app'].compilerVersion,
hx: isInHBuilderX ? 1 : 0,
et: type,
em: err
})
var hash = this._getMD5(data)
if (this._cacheList.includes(hash)) {
return
}
this._cacheList.push(hash)
setTimeout(() => {
this._doReport(data)
}, 10)
}
_doReport (data) {
const req = this.https.request({
hostname: this.HOST,
port: 443,
path: this.PATH,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
})
req.write(data)
req.end()
}
_shouldReport (err = '') {
try {
const errMsg = err.toString()
const errorIndex = this.EXCLUDE_ERROR_LIST.findIndex(item => errMsg.includes(item))
if (errorIndex >= 0) {
return false
}
// 目前简单的上报逻辑为:错误信息中包含@dcloudio包名
if (
errMsg.includes('@dcloudio') &&
!errMsg.includes('Errors compiling template')
) {
return true
}
} catch (e) {}
return false
}
_getMD5 (str) {
return this.crypto.createHash('md5').update(str).digest('hex')
}
_getMac () {
let mac
const network = this.os.networkInterfaces()
for (const key in network) {
const array = network[key]
for (let i = 0; i < array.length; i++) {
const item = array[i]
if (!item.family || (item.mac && item.mac === '00:00:00:00:00:00')) {
continue
}
if (item.family === 'IPv4' || item.family === 'IPv6') {
mac = item.mac
break
}
}
}
return mac
}
get crypto () {
if (this._crypto == null) {
this._crypto = require('crypto')
}
return this._crypto
}
}
Object.assign(ErrorReport.prototype, {
HOST: '96f0e031-f37a-48ef-84c7-2023f6360c0a.bspapp.com',
PATH: '/http/uni-app-compiler',
EXCLUDE_ERROR_LIST: ['uni-app-compiler', 'Error: ENOENT: no such file or directory']
})
function report (type, err) {
// ErrorReport.instance.report(type, err)
}
global.__error_reporting__ = report
process
.on('unhandledRejection', (reason, p) => {
console.log(reason)
// global.__error_reporting__ && global.__error_reporting__('unhandledRejection', reason)
})
.on('uncaughtException', err => {
console.log(err)
// global.__error_reporting__ && global.__error_reporting__('uncaughtException', err.stack)
})
+80
View File
@@ -0,0 +1,80 @@
function typof (v) {
var s = Object.prototype.toString.call(v)
return s.substring(8, s.length - 1)
}
function isDebugMode () {
/* eslint-disable no-undef */
return typeof __channelId__ === 'string' && __channelId__
}
function jsonStringifyReplacer (k, p) {
switch (typof(p)) {
case 'Function':
return 'function() { [native code] }'
default :
return p
}
}
export function log (type) {
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key]
}
console[type].apply(console, args)
}
export default function formatLog () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key]
}
var type = args.shift()
if (isDebugMode()) {
args.push(args.pop().replace('at ', 'uni-app:///'))
return console[type].apply(console, args)
}
var msgs = args.map(function (v) {
var type = Object.prototype.toString.call(v).toLowerCase()
if (type === '[object object]' || type === '[object array]') {
try {
v = '---BEGIN:JSON---' + JSON.stringify(v, jsonStringifyReplacer) + '---END:JSON---'
} catch (e) {
v = type
}
} else {
if (v === null) {
v = '---NULL---'
} else if (v === undefined) {
v = '---UNDEFINED---'
} else {
var vType = typof(v).toUpperCase()
if (vType === 'NUMBER' || vType === 'BOOLEAN') {
v = '---BEGIN:' + vType + '---' + v + '---END:' + vType + '---'
} else {
v = String(v)
}
}
}
return v
})
var msg = ''
if (msgs.length > 1) {
var lastMsg = msgs.pop()
msg = msgs.join('---COMMA---')
if (lastMsg.indexOf(' at ') === 0) {
msg += lastMsg
} else {
msg += '---COMMA---' + lastMsg
}
} else {
msg = msgs[0]
}
console[type](msg)
}
+188
View File
@@ -0,0 +1,188 @@
var validDivisionCharRE = /[\w).+\-_$\]]/
function parseFilters (exp) {
var inSingle = false
var inDouble = false
var inTemplateString = false
var inRegex = false
var curly = 0
var square = 0
var paren = 0
var lastFilterIndex = 0
var c, prev, i, expression, filters
for (i = 0; i < exp.length; i++) {
prev = c
c = exp.charCodeAt(i)
if (inSingle) {
if (c === 0x27 && prev !== 0x5C) {
inSingle = false
}
} else if (inDouble) {
if (c === 0x22 && prev !== 0x5C) {
inDouble = false
}
} else if (inTemplateString) {
if (c === 0x60 && prev !== 0x5C) {
inTemplateString = false
}
} else if (inRegex) {
if (c === 0x2f && prev !== 0x5C) {
inRegex = false
}
} else if (
c === 0x7C && // pipe
exp.charCodeAt(i + 1) !== 0x7C &&
exp.charCodeAt(i - 1) !== 0x7C &&
!curly && !square && !paren
) {
if (expression === undefined) {
// first filter, end of expression
lastFilterIndex = i + 1
expression = exp.slice(0, i).trim()
} else {
pushFilter()
}
} else {
switch (c) {
case 0x22:
inDouble = true
break // "
case 0x27:
inSingle = true
break // '
case 0x60:
inTemplateString = true
break // `
case 0x28:
paren++
break // (
case 0x29:
paren--
break // )
case 0x5B:
square++
break // [
case 0x5D:
square--
break // ]
case 0x7B:
curly++
break // {
case 0x7D:
curly--
break // }
}
if (c === 0x2f) { // /
var j = i - 1
/* eslint-disable no-void */
var p = (void 0)
// find first non-whitespace prev char
for (; j >= 0; j--) {
p = exp.charAt(j)
if (p !== ' ') {
break
}
}
if (!p || !validDivisionCharRE.test(p)) {
inRegex = true
}
}
}
}
if (expression === undefined) {
expression = exp.slice(0, i).trim()
} else if (lastFilterIndex !== 0) {
pushFilter()
}
function pushFilter () {
(filters || (filters = [])).push(exp.slice(lastFilterIndex, i).trim())
lastFilterIndex = i + 1
}
if (filters) {
for (i = 0; i < filters.length; i++) {
expression = wrapFilter(expression, filters[i])
}
}
return expression
}
function wrapFilter (exp, filter) {
var i = filter.indexOf('(')
if (i < 0) {
// _f: resolveFilter
return ('_f("' + filter + '")(' + exp + ')')
} else {
var name = filter.slice(0, i)
var args = filter.slice(i + 1)
return ('_f("' + name + '")(' + exp + (args !== ')' ? ',' + args : args))
}
}
const defaultTagRE = /\{\{((?:.|\n)+?)\}\}/g
function parseText (
text
) {
const tokens = []
const rawTokens = []
let lastIndex = defaultTagRE.lastIndex = 0
let match, index, tokenValue
while ((match = defaultTagRE.exec(text))) {
index = match.index
// push text token
if (index > lastIndex) {
rawTokens.push(tokenValue = text.slice(lastIndex, index))
tokens.push(JSON.stringify(tokenValue))
}
// tag token
var exp = parseFilters(match[1].trim())
tokens.push(('_s(' + exp + ')'))
rawTokens.push({
'@binding': exp
})
lastIndex = index + match[0].length
}
if (lastIndex < text.length) {
rawTokens.push(tokenValue = text.slice(lastIndex))
tokens.push(JSON.stringify(tokenValue))
}
return {
expression: tokens.join('+'),
tokens: rawTokens
}
}
module.exports = {
postTransformNode (el) { // 重新格式化 text 节点,应该使用postTransformNode,但 mpvue 使用的 template-compiler 较老,导致 postTransformNode 时机不对
const children = el.children
if (children && children.length) {
children.forEach(childEl => {
if (childEl.text) {
const text = childEl.text.trim()
if (childEl.type === 2) {
try {
const {
expression,
tokens
} = parseText(text)
childEl.expression = expression
childEl.tokens = tokens
childEl.text = text
} catch (e) {
console.log(e)
}
} else {
childEl.text = text
}
}
})
}
return ''
}
}
+9
View File
@@ -0,0 +1,9 @@
(function () {
var userAgent = navigator.userAgent
window.addEventListener('resize', function () {
if (navigator.userAgent !== userAgent) {
/* eslint-disable no-undef */
location.reload()
}
})
})()
+119
View File
@@ -0,0 +1,119 @@
const {
tags
} = require('@dcloudio/uni-cli-shared')
const parser = require('@babel/parser')
const t = require('@babel/types')
const simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/
function isFunction (expr) {
try {
const body = parser.parse(`(${expr})`).program.body[0]
const expression = body.expression
return t.isFunctionDeclaration(body) || t.isArrowFunctionExpression(expression) || t.isFunctionExpression(
expression)
} catch (error) {}
}
function processEvent (expr, filterModules) {
const isMethodPath = simplePathRE.test(expr)
if (isMethodPath || isFunction(expr)) {
if (filterModules.find(name => expr.indexOf(name + '.') === 0)) {
return `
$event = $handleWxsEvent($event);
(${expr})($event, $getComponentDescriptor())
`
} else {
expr = `(${expr})(...arguments)`
}
}
return `
arguments[0] = $event = $handleEvent($event);
${expr}
`
}
function hasOwn (obj, key) {
return hasOwnProperty.call(obj, key)
}
const deprecated = {
events: {
tap: 'click',
longtap: 'longpress'
}
}
function addTag (tag) {
if (!process.UNI_TAGS) {
process.UNI_TAGS = new Set()
}
process.UNI_TAGS.add(tag)
}
module.exports = {
h5: true,
modules: [require('../format-text'), {
preTransformNode (el, options) {
if (el.tag.indexOf('v-uni-') === 0) {
addTag(el.tag.replace('v-uni-', ''))
} else if (hasOwn(tags, el.tag)) {
addTag(el.tag)
el.tag = 'v-uni-' + el.tag
}
},
postTransformNode (el, {
warn,
filterModules
}) {
if (el.tag === 'block') {
el.tag = 'template'
const vForKey = el.key
if (vForKey) {
delete el.key
el.children.forEach((childEl, index) => {
const childVForKey = childEl.key
if (childVForKey) {
childEl.key = `${childVForKey}+'_'+${vForKey}+'_${index}'`
} else {
childEl.key = `${vForKey}+'_${index}'`
}
})
}
}
if (el.events || el.nativeEvents) {
filterModules = filterModules || []
const {
events: eventsMap
} = deprecated
// const warnLogs = new Set()
normalizeEvent(el.events, eventsMap, filterModules)
normalizeEvent(el.nativeEvents, eventsMap, filterModules)
}
}
}]
}
function normalizeEvent (events, eventsMap, filterModules) {
if (!events) {
return
}
Object.keys(events).forEach(name => {
// 过时事件类型转换
if (eventsMap[name]) {
events[eventsMap[name]] = events[name]
delete events[name]
// warnLogs.add(`警告:事件${name}已过时,推荐使用${eventsMap[name]}代替`)
name = eventsMap[name]
}
const handlers = events[name]
if (Array.isArray(handlers)) {
handlers.forEach(handler => {
handler.value = processEvent(handler.value, filterModules)
})
} else {
handlers.value = processEvent(handlers.value, filterModules)
}
})
}
+61
View File
@@ -0,0 +1,61 @@
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
}
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)
module.rule('css').oneOf('vue').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('css').oneOf('normal-modules').use('cssnano').loader('postcss-loader').options(
cssnanoOptions)
module.rule('css').oneOf('normal').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('postcss').oneOf('vue-modules').use('cssnano').loader('postcss-loader').options(
cssnanoOptions)
module.rule('postcss').oneOf('vue').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('postcss').oneOf('normal-modules').use('cssnano').loader('postcss-loader').options(
cssnanoOptions)
module.rule('postcss').oneOf('normal').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('scss').oneOf('vue-modules').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('scss').oneOf('vue').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('scss').oneOf('normal-modules').use('cssnano').loader('postcss-loader').options(
cssnanoOptions)
module.rule('scss').oneOf('normal').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('sass').oneOf('vue-modules').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('sass').oneOf('vue').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('sass').oneOf('normal-modules').use('cssnano').loader('postcss-loader').options(
cssnanoOptions)
module.rule('sass').oneOf('normal').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('less').oneOf('vue-modules').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('less').oneOf('vue').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('less').oneOf('normal-modules').use('cssnano').loader('postcss-loader').options(
cssnanoOptions)
module.rule('less').oneOf('normal').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('stylus').oneOf('vue-modules').use('cssnano').loader('postcss-loader').options(
cssnanoOptions)
module.rule('stylus').oneOf('vue').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
module.rule('stylus').oneOf('normal-modules').use('cssnano').loader('postcss-loader').options(
cssnanoOptions)
module.rule('stylus').oneOf('normal').use('cssnano').loader('postcss-loader').options(cssnanoOptions)
}
+198
View File
@@ -0,0 +1,198 @@
const fs = require('fs')
const path = require('path')
const webpack = require('webpack')
const {
getMainEntry,
getH5Options,
getPlatformStat,
getPlatformPush,
getPlatformUniCloud,
getDevUniConsoleCode
} = require('@dcloudio/uni-cli-shared')
const {
getGlobalUsingComponentsCode
} = require('@dcloudio/uni-cli-shared/lib/pages')
const modifyVueLoader = require('../vue-loader')
const WebpackHtmlAppendPlugin = require('../../packages/webpack-html-append-plugin')
const WebpackUniAppPlugin = require('../../packages/webpack-uni-app-loader/plugin/index')
function resolve (dir) {
return path.resolve(__dirname, '../../', dir)
}
const {
title,
publicPath,
template,
devServer
} = getH5Options()
const runtimePath = '@dcloudio/uni-mp-weixin/dist/mp.js'
const wxsPath = '@dcloudio/uni-mp-weixin/dist/wxs.js'
const uniCloudPath = path.resolve(__dirname, '../../packages/uni-cloud/dist/index.js')
function getProvides () {
return {
__f__: [path.resolve(__dirname, '../format-log.js'), 'log'],
uniCloud: [uniCloudPath, 'uniCloud'],
'wx.nextTick': [runtimePath, 'nextTick'],
Page: [runtimePath, 'Page'],
Component: [runtimePath, 'Component'],
Behavior: [runtimePath, 'Behavior'],
getDate: [wxsPath, 'getDate'],
getRegExp: [wxsPath, 'getRegExp']
}
}
const plugins = [
new WebpackUniAppPlugin(),
new webpack.ProvidePlugin(getProvides())
]
if (process.env.NODE_ENV !== 'production') {
plugins.push(new WebpackHtmlAppendPlugin(
`
<script>
${fs.readFileSync(path.resolve(__dirname, './auto-reload.js'), 'utf8')}
</script>
`
))
}
const vueConfig = {
parallel: false, // 因为传入了自定义 compiler,避免参数丢失,禁用parallel
publicPath,
pages: {
index: {
// page 的入口
entry: path.resolve(process.env.UNI_INPUT_DIR, getMainEntry()),
// 模板来源
template,
// 在 dist/index.html 的输出
filename: 'index.html',
// 当使用 title 选项时,
// template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
title,
// 在这个页面中包含的块,默认情况下会包含
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ['chunk-vendors', 'chunk-common', 'index'],
baseUrl: publicPath
}
}
}
if (devServer && Object.keys(devServer).length) {
vueConfig.devServer = devServer
}
module.exports = {
vueConfig,
webpackConfig (webpackConfig) {
let useBuiltIns = 'usage'
const statCode = getPlatformStat()
const pushCode = getPlatformPush()
const uniCloudCode = getPlatformUniCloud()
try {
const babelConfig = require(path.resolve(process.env.UNI_CLI_CONTEXT, 'babel.config.js'))
useBuiltIns = babelConfig.presets[0][1].useBuiltIns
} catch (e) {}
const beforeCode = (useBuiltIns === 'entry' ? 'import \'@babel/polyfill\';' : '') +
getDevUniConsoleCode() + `import 'uni-pages';import 'uni-${process.env.UNI_PLATFORM}';`
return {
resolve: {
extensions: ['.uts', '.nvue'],
alias: {
'vue-router': resolve('packages/h5-vue-router'),
'uni-h5': require.resolve('@dcloudio/uni-h5')
}
},
module: {
rules: [{
test: path.resolve(process.env.UNI_INPUT_DIR, getMainEntry()),
use: [{
loader: path.resolve(__dirname, '../../packages/wrap-loader'),
options: {
before: [
beforeCode + require('../util').getAutomatorCode() + statCode + pushCode + uniCloudCode +
getGlobalUsingComponentsCode()
]
}
}]
}, {
test: /App\.vue$/,
use: {
loader: path.resolve(__dirname, '../../packages/wrap-loader'),
options: {
before: ['<template><App :keepAliveInclude="keepAliveInclude"/></template>']
}
}
}, { // 解析组件,css 等
resourceQuery: /vue&type=script/,
use: [{
loader: path.resolve(__dirname,
'../../packages/webpack-uni-app-loader/using-components')
}]
}, {
resourceQuery: /vue&type=template/,
use: [{
loader: resolve('packages/webpack-uni-app-loader/filter-modules-template.js')
}, {
loader: '@dcloudio/vue-cli-plugin-uni/packages/webpack-uni-app-loader/page-meta'
}]
}, {
resourceQuery: [/lang=wxs/, /blockType=wxs/],
use: [{
loader: resolve('packages/webpack-uni-filter-loader')
}]
}]
},
resolveLoader: {
alias: {
'vue-style-loader': resolve('packages/h5-vue-style-loader')
}
},
plugins,
optimization: {
moduleIds: webpack.version[0] > 4 ? 'deterministic' : 'hashed'
},
devServer: webpack.version[0] > 4 ? {
watchFiles: {
options: require('../util').getWatchOptions()
}
} : {
watchOptions: require('../util').getWatchOptions()
}
}
},
chainWebpack (webpackConfig, vueOptions, api) {
webpackConfig.plugins.delete('copy')
if (!process.env.UNI_OPT_PREFETCH) {
webpackConfig.plugins.delete('prefetch-index')
}
if (!process.env.UNI_OPT_PRELOAD) {
webpackConfig.plugins.delete('preload-index')
}
const compilerOptions = require('./compiler-options')
if (publicPath === './') {
compilerOptions.publicPath = publicPath
}
modifyVueLoader(webpackConfig, {
isH5: true,
hotReload: true
}, compilerOptions, api)
if (process.env.NODE_ENV === 'production') {
require('./cssnano-options')(webpackConfig)
}
}
}
+55
View File
@@ -0,0 +1,55 @@
const {
camelize,
convertStaticStyle
} = require('@dcloudio/uni-cli-shared')
module.exports = {
modules: [require('./format-text'), {
preTransformNode (el, {
warn
}) {
if (el.attrsMap) {
if (el.attrsMap.style) {
el.attrsMap.style = convertStaticStyle(el.attrsMap.style)
}
if (process.env.UNI_PLATFORM === 'mp-baidu') { // fixed data-index => dataIndex
Object.keys(el.attrsMap).forEach(attr => {
if (attr.indexOf(':data-') === 0) {
el.attrsMap[camelize(attr)] = el.attrsMap[attr]
delete el.attrsMap[attr]
}
})
}
}
if (el.attrsList && el.attrsList.length) {
el.attrsList.forEach(attr => {
if (attr.name === 'style' && attr.value) {
attr.value = convertStaticStyle(attr.value)
}
if (process.env.UNI_PLATFORM === 'mp-baidu') { // fixed data-index => dataIndex
if (attr.name.indexOf(':data-') === 0) {
attr.name = camelize(attr.name)
}
}
})
}
},
postTransformNode (el) {
if (process.env.UNI_PLATFORM === 'mp-alipay') {
if (el.tag === 'slot') {
if (!el.children.length) {
el.children.push({
type: 1,
tag: 'view',
attrsList: [],
attrsMap: {},
parent: el,
children: [],
plain: true
})
}
}
}
}
}]
}
+386
View File
@@ -0,0 +1,386 @@
const path = require('path')
const webpack = require('webpack')
const {
parseEntry,
getMainEntry,
normalizePath,
getPlatformExts,
getPlatformCssnano,
getPlatformStat,
getPlatformPush,
getPlatformUniCloud,
createSource,
deleteAsset,
getDevUniConsoleCode
} = require('@dcloudio/uni-cli-shared')
const WebpackUniAppPlugin = require('../../packages/webpack-uni-app-loader/plugin/index')
const modifyVueLoader = require('../vue-loader')
const {
createTemplateCacheLoader
} = require('../cache-loader')
function createUniMPPlugin () {
const WebpackUniMPPlugin = require('@dcloudio/webpack-uni-mp-loader/lib/plugin/index-new')
return new WebpackUniMPPlugin()
}
const createWxMpIndependentPlugins = require('@dcloudio/uni-mp-weixin/lib/createIndependentPlugin')
const UniTips = require('./tips')
function getProvides () {
const uniPath = require('@dcloudio/uni-cli-shared/lib/platform').getMPRuntimePath()
const uniCloudPath = path.resolve(__dirname, '../../packages/uni-cloud/dist/index.js')
const provides = {
uni: [uniPath, 'default'],
uniCloud: [uniCloudPath, 'uniCloud']
}
if (process.env.UNI_USING_VUE3) {
provides.uni = ['@dcloudio/uni-' + process.env.UNI_PLATFORM + '/dist/uni.api.esm.js', 'default']
provides.createMiniProgramApp = [uniPath, 'createApp']
}
if (process.env.UNI_USING_COMPONENTS) {
if (process.env.UNI_SUBPACKGE) {
provides.createApp = [uniPath, 'createSubpackageApp']
} else if (process.env.UNI_MP_PLUGIN) {
provides.createApp = [uniPath, 'createPlugin']
} else {
provides.createApp = [uniPath, 'createApp']
}
provides.createPage = [uniPath, 'createPage']
provides.createComponent = [uniPath, 'createComponent']
}
if (
process.env.UNI_PLATFORM === 'app-plus' &&
process.env.UNI_USING_V8
) {
provides.__f__ = [path.resolve(__dirname, '../format-log.js'), 'default']
const cryptoProvide = [path.resolve(__dirname, '../crypto.js'), 'default']
provides.crypto = cryptoProvide
provides['window.crypto'] = cryptoProvide
provides['global.crypto'] = cryptoProvide
}
// TODO 目前依赖库 megalo 通过判断 wx 对象是否存在来识别平台做不同处理
if (
process.env.UNI_PLATFORM !== 'mp-qq' &&
process.env.UNI_PLATFORM !== 'mp-weixin' &&
process.env.UNI_PLATFORM !== 'app-plus'
) { // 非微信小程序,自动注入 wx 对象
provides.wx = provides.uni
}
if (process.env.UNI_PLATFORM === 'mp-weixin') {
provides.wx = [path.resolve(uniPath, '../wx.js'), 'default']
}
return provides
}
function processWxss (compilation, name, assets) {
const dirname = path.dirname(name)
const mainWxssCode = `@import "${normalizePath(path.relative(dirname, 'common/main.wxss'))}";`
const code = `${mainWxssCode}` + assets[name].source().toString()
compilation.updateAsset(name, createSource(code))
}
const parseRequirePath = path => path.startsWith('common') ? `./${path}` : path
function procssJs (compilation, name, assets, hasVendor) {
const dirname = path.dirname(name)
const runtimeJsCode = `require('${normalizePath(parseRequirePath(path.relative(dirname, 'common/runtime.js')))}');`
const vendorJsCode = hasVendor
? `require('${normalizePath(parseRequirePath(path.relative(dirname, 'common/vendor.js')))}');` : ''
const mainJsCode = `require('${normalizePath(parseRequirePath(path.relative(dirname, 'common/main.js')))}');`
const code = `${runtimeJsCode}${vendorJsCode}${mainJsCode}` + assets[name].source().toString()
compilation.updateAsset(name, createSource(code))
}
function processAssets (compilation) {
const assets = compilation.assets
const hasMainWxss = assets['common/main.wxss']
const hasVendor = assets['common/vendor.js']
Object.keys(assets).forEach(name => {
if (name.startsWith('common')) {
return
}
const extname = path.extname(name)
if (extname === '.wxss' && hasMainWxss && process.UNI_ENTRY[name.replace(extname, '')]) {
processWxss(compilation, name, assets)
} else if (extname === '.js') {
procssJs(compilation, name, assets, hasVendor)
}
})
// delete assets['common/main.js']
deleteAsset(compilation, 'app.js')
deleteAsset(compilation, 'app.json')
deleteAsset(compilation, 'app.wxss')
deleteAsset(compilation, 'project.config.json')
}
class PreprocessAssetsPlugin {
apply (compiler) {
if (webpack.version[0] > 4) {
compiler.hooks.compilation.tap('PreprocessAssetsPlugin', compilation => {
compilation.hooks.processAssets.tap({
name: 'PreprocessAssetsPlugin',
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
}, (_) => {
processAssets(compilation)
})
})
} else {
compiler.hooks.emit.tap('PreprocessAssetsPlugin', (compilation) => processAssets(compilation))
}
}
}
function initSubpackageConfig (webpackConfig, vueOptions) {
if (process.env.UNI_OUTPUT_DEFAULT_DIR === process.env.UNI_OUTPUT_DIR) { // 未自定义output
process.env.UNI_OUTPUT_DIR = path.resolve(process.env.UNI_OUTPUT_DIR, (process.env.UNI_SUBPACKGE || process.env
.UNI_MP_PLUGIN))
}
vueOptions.outputDir = process.env.UNI_OUTPUT_DIR
webpackConfig.output.path(process.env.UNI_OUTPUT_DIR)
webpackConfig.output.set(webpack.version[0] > 4 ? 'chunkLoadingGlobal' : 'jsonpFunction', 'webpackJsonp_' + (process
.env.UNI_SUBPACKGE || process.env.UNI_MP_PLUGIN))
}
function addToUniEntry (fileName) {
fileName && (process.UNI_ENTRY[fileName.split('.')[0]] = path.resolve(process.env.UNI_INPUT_DIR, fileName))
}
module.exports = {
vueConfig: {
parallel: false
},
webpackConfig (webpackConfig, vueOptions, api) {
if (!webpackConfig.optimization) {
webpackConfig.optimization = {}
}
// disable noEmitOnErrors
if (webpack.version[0] > 4) {
webpackConfig.optimization.emitOnErrors = true
} else {
webpackConfig.optimization.noEmitOnErrors = false
}
webpackConfig.optimization.runtimeChunk = {
name: 'common/runtime'
}
webpackConfig.optimization.splitChunks = require('../split-chunks')()
if (webpack.version[0] > 4) {
webpackConfig.optimization.chunkIds = 'named'
}
parseEntry()
const statCode = getPlatformStat()
const pushCode = getPlatformPush()
const uniCloudCode = getPlatformUniCloud()
let beforeCode = getDevUniConsoleCode() + 'import \'uni-pages\';'
const plugins = [
new WebpackUniAppPlugin(),
createUniMPPlugin(),
new webpack.ProvidePlugin(getProvides()),
...createWxMpIndependentPlugins()
]
if ((process.env.UNI_SUBPACKGE || process.env.UNI_MP_PLUGIN) && process.env.UNI_SUBPACKGE !== 'main') {
plugins.push(new PreprocessAssetsPlugin())
}
{
const globalEnv = process.env.UNI_PLATFORM === 'mp-alipay' ? 'my' : 'wx';
[].concat(
process.env.UNI_MP_PLUGIN
? process.env.UNI_MP_PLUGIN_MAIN
: JSON.parse(process.env.UNI_MP_PLUGIN_EXPORT)
).forEach(fileName => addToUniEntry(fileName))
beforeCode += `
// @ts-ignore
${globalEnv}.__webpack_require_UNI_MP_PLUGIN__ = __webpack_require__;`
}
const alias = { // 仅 mp-weixin
'mpvue-page-factory': require.resolve(
'@dcloudio/vue-cli-plugin-uni/packages/mpvue-page-factory')
}
if (process.env.UNI_USING_VUE3) {
alias.vuex = require.resolve('@dcloudio/vue-cli-plugin-uni/packages/vuex')
alias['@vue/devtools-api'] = require.resolve('@dcloudio/vue-cli-plugin-uni/packages/@vue/devtools-api')
alias['vue-i18n'] = require.resolve('@dcloudio/vue-cli-plugin-uni/packages/vue3/node_modules/vue-i18n')
alias['@dcloudio/uni-app'] = require.resolve('@dcloudio/vue-cli-plugin-uni/packages/uni-app')
}
// 使用外层依赖的版本
alias['regenerator-runtime'] = require.resolve('regenerator-runtime')
const output = {
pathinfo: true,
filename: '[name].js',
chunkFilename: '[id].js',
globalObject: process.env.UNI_PLATFORM === 'mp-alipay' ? 'my' : 'global'
// sourceMapFilename: '../.sourcemap/' + process.env.UNI_PLATFORM + '/[name].js.map'
}
if (process.env.NODE_ENV === 'production' || process.env.UNI_MINIMIZE === 'true') {
output.pathinfo = false
}
if (process.env.UNI_PLATFORM === 'mp-weixin' && process.env.NODE_ENV === 'production') {
plugins.push(new UniTips())
}
return {
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
entry () {
return process.UNI_ENTRY
},
output,
performance: {
hints: false
},
resolve: {
extensions: ['.uts', '.nvue'],
alias
},
module: {
rules: [{
test: path.resolve(process.env.UNI_INPUT_DIR, getMainEntry()),
use: [{
loader: path.resolve(__dirname, '../../packages/wrap-loader'),
options: {
before: [
beforeCode + require('../util').getAutomatorCode() + statCode + pushCode + uniCloudCode
]
}
}, {
loader: '@dcloudio/webpack-uni-mp-loader/lib/main'
}]
}, {
resourceQuery: /vue&type=script/,
use: [{
loader: '@dcloudio/webpack-uni-mp-loader/lib/script'
}]
}, {
resourceQuery: /vue&type=template/,
use: [{
loader: '@dcloudio/webpack-uni-mp-loader/lib/template'
}, {
loader: '@dcloudio/vue-cli-plugin-uni/packages/webpack-uni-app-loader/page-meta'
}]
}, createTemplateCacheLoader(api), {
resourceQuery: [
/lang=wxs/,
/lang=filter/,
/lang=sjs/,
/blockType=wxs/,
/blockType=filter/,
/blockType=sjs/
],
use: [{
loader: require.resolve(
'@dcloudio/vue-cli-plugin-uni/packages/webpack-uni-filter-loader')
}]
}]
},
plugins
}
},
chainWebpack (webpackConfig, vueOptions, api) {
if (process.env.UNI_PLATFORM === 'mp-baidu') {
webpackConfig.module
.rule('js')
.exclude
.add(/\.filter\.js$/)
}
const compilerOptions = process.env.UNI_USING_COMPONENTS ? {} : require('../mp-compiler-options')
modifyVueLoader(webpackConfig, {}, compilerOptions, api)
const styleExt = getPlatformExts().style
webpackConfig.plugin('extract-css')
.init((Plugin, args) => new Plugin({
filename: '[name]' + styleExt,
// mini-css-extract-plugin 2.3.0 版本以上可用
// https://github.com/webpack-contrib/mini-css-extract-plugin/releases/tag/v2.3.0
runtime: false
}))
// 去除 mini-css-extract-plugin 2.3.0 以下版本的 css runtime
// https://github.com/webpack-contrib/mini-css-extract-plugin/blob/e200b083e5a437026d6021262d4ac56088b39e65/src/index.js#L273
if (require('semver').lt(require('mini-css-extract-plugin/package.json').version, '2.3.0')) {
const pluginName = 'skip-mini-css-extract-runtime'
webpackConfig.plugin(pluginName).use(
class SkipMiniCssExtractRuntimePlugin {
apply (compiler) {
compiler.hooks.thisCompilation.tap(pluginName, compilation => {
const { mainTemplate } = compilation
const reg = /\/\/ mini-css-extract-plugin CSS loading[\s\S]*installedCssChunks\[chunkId\] = 0;\s*\}\)\);\s*\}/
mainTemplate.hooks.requireEnsure.tap(pluginName, (source, chunk) => {
return reg.test(source) ? source.replace(reg, '') : source
})
})
}
}
)
}
if (
process.env.NODE_ENV === 'production' &&
process.env.UNI_PLATFORM !== 'app-plus'
) {
// 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.NODE_ENV === 'production' && webpack.version[0] > 4) {
// 暂时禁用,否则导致 provide 被压缩和裁剪
webpackConfig.optimization.usedExports(false)
}
if (process.env.UNI_SUBPACKGE || process.env.UNI_MP_PLUGIN) {
initSubpackageConfig(webpackConfig, vueOptions)
}
webpackConfig.plugins.delete('hmr')
webpackConfig.plugins.delete('html')
webpackConfig.plugins.delete('copy')
webpackConfig.plugins.delete('preload')
webpackConfig.plugins.delete('prefetch')
}
}
+67
View File
@@ -0,0 +1,67 @@
const fs = require('fs')
const path = require('path')
const {
isInHBuilderX
} = require('@dcloudio/uni-cli-shared')
class UniTips {
apply (compiler) {
compiler.hooks.emit.tap('PreprocessAssetsPlugin', compilation => {
const assets = compilation.assets
let hasAd = false
try {
Object.keys(assets).forEach(name => {
if (hasAd) {
return
}
if (!name.startsWith('common') && !name.startsWith('pages')) {
return
}
const extname = path.extname(name)
if (extname !== '.js') {
return
}
if (!hasAd && !process.env.USE_UNI_AD) {
hasAd = assets[name]._value.match(/createRewardedVideoAd|createInterstitialAd/)
}
})
setTimeout(() => {
if (hasAd) {
console.log(
'推荐使用uni-ad微信小程序版广告,无开通门槛、提前结算、插件丰富,助力广告变现。详情: https://uniapp.dcloud.net.cn/component/ad-weixin.html'
)
}
let projectRoot = ''
if (isInHBuilderX) {
projectRoot = process.env.UNI_INPUT_DIR
} else {
projectRoot = process.env.UNI_CLI_CONTEXT
}
const paths = fs.readdirSync(projectRoot)
const useUniCloud = paths.find((name) => {
return name.includes('uniCloud-')
})
if (!useUniCloud && assets['project.config.json']) {
const pcjString = assets['project.config.json'].source()
const pcjJson = JSON.parse(pcjString)
if (typeof pcjJson.cloudfunctionRoot === 'string' && pcjJson.cloudfunctionRoot.length > 0) {
console.log(
'欢迎使用uniCloud,价格更便宜、开发更方便、生态更丰富的云开发。详情: https://uniapp.dcloud.net.cn/uniCloud/wx2unicloud.html'
)
}
}
}, 100)
} catch (e) {}
})
}
}
module.exports = UniTips
+107
View File
@@ -0,0 +1,107 @@
const fs = require('fs')
const path = require('path')
const webpack = require('webpack')
const {
pathToRegexp
} = require('@dcloudio/uni-cli-shared/lib/util')
module.exports = function initOptions (options) {
const {
getPlatformScss,
getPlatformSass
} = require('@dcloudio/uni-cli-shared')
if (!options.transpileDependencies) {
options.transpileDependencies = []
}
// 增加 src/node_modules 解析
options.transpileDependencies.push(pathToRegexp(path.resolve(process.env.UNI_INPUT_DIR, 'node_modules'), {
start: true
}))
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-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-push')
if (process.env.UNI_PLATFORM !== 'mp-weixin') { // mp runtime
options.transpileDependencies.push('@dcloudio/uni-mp-weixin')
}
if (process.env.UNI_PLATFORM === 'h5') { // h5 dev 用到了这两个,需要 babel
options.transpileDependencies.push('ansi-regex')
options.transpileDependencies.push('strip-ansi')
}
if (!options.css) {
options.css = {}
}
if (process.env.UNI_PLATFORM === 'h5' || process.env.UNI_USING_V3) {
options.css.extract = false
} else {
options.css.extract = true
}
if (!options.css.loaderOptions) {
options.css.loaderOptions = {}
}
if (!options.css.loaderOptions.postcss) {
options.css.loaderOptions.postcss = {}
}
if (!options.css.loaderOptions.sass) {
options.css.loaderOptions.sass = {}
}
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 全局变量
const isSass = fs.existsSync(path.resolve(process.env.UNI_INPUT_DIR, 'uni.sass'))
const isScss = fs.existsSync(path.resolve(process.env.UNI_INPUT_DIR, 'uni.scss'))
let sassData = isSass ? getPlatformSass() : getPlatformScss()
if (process.env.UNI_SASS_IMPLEMENTATION_NAME === 'dart-sass') {
if (isSass) {
sassData = '@use "@/uni.sass" as *'
} else if (isScss) {
sassData = '@use "@/uni.scss" as *;'
}
} else {
if (isSass) {
sassData = '@import "@/uni.sass"'
} else if (isScss) {
sassData = `${sassData}
@import "@/uni.scss";`
}
}
if (!options.css.loaderOptions.sass.sassOptions) {
options.css.loaderOptions.sass.sassOptions = {}
}
// 指定 outputStyle, 否则 production 模式下会被默认成 compressed
const outputStyle = options.css.loaderOptions.sass.sassOptions.outputStyle
if (!outputStyle || outputStyle === 'compressed') {
options.css.loaderOptions.sass.sassOptions.outputStyle = 'expanded'
}
options.css.loaderOptions.sass.prependData = sassData
const userPostcssConfigPath = path.resolve(process.env.UNI_INPUT_DIR, 'postcss.config.js')
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 = configPath
}
}
+257
View File
@@ -0,0 +1,257 @@
const path = require('path')
const {
normalizePath
} = require('@dcloudio/uni-cli-shared')
const subPkgsInfo = Object.values(process.UNI_SUBPACKAGES)
const normalFilter = ({
independent
}) => !independent
const independentFilter = ({
independent
}) => independent
const map2Root = ({
root
}) => root + '/'
const normalSubPackageRoots = subPkgsInfo.filter(normalFilter).map(map2Root)
const independentSubpackageRoots = subPkgsInfo.filter(independentFilter).map(map2Root)
function createCacheGroups () {
const cacheGroups = {}
if (process.UNI_CONFUSION) { // 加密
cacheGroups.confusion = {
enforce: true,
test: function (module) {
if (!module.resource) {
return false
}
if (process.UNI_CONFUSION.includes(normalizePath(module.resource))) {
return true
}
return false
},
name: 'app-confusion',
chunks: 'all'
}
}
process.env.UNI_OPT_SUBPACKAGES && Object.keys(process.UNI_SUBPACKAGES).forEach(root => {
cacheGroups[root] = {
enforce: true,
test: function (module) {
if (!module.resource) {
return false
}
if (normalizePath(module.resource).includes(root + '/')) {
return true
}
return false
},
name: root + '/app-sub-service',
chunks: 'all'
}
})
return cacheGroups
}
module.exports = function getSplitChunks () {
const {
normalizePath
} = require('@dcloudio/uni-cli-shared')
if (process.env.UNI_USING_V3) {
return {
cacheGroups: createCacheGroups()
}
}
if (!process.env.UNI_USING_COMPONENTS) {
return {
cacheGroups: {
commons: {
minChunks: 2,
name: 'common/vendor',
chunks: 'all'
}
}
}
}
const mainPath = normalizePath(path.resolve(process.env.UNI_INPUT_DIR, 'main.'))
if (!process.env.UNI_OPT_SUBPACKAGES) {
return {
chunks (chunk) { // 防止 node_modules 内 vue 组件被 split
return (chunk.name || '').indexOf('node-modules') !== 0
},
cacheGroups: {
default: false,
vendors: false,
commons: {
test (module) {
if (module.type === 'css/mini-extract') {
return false
}
if (module.resource && (
module.resource.indexOf('.vue') !== -1 ||
module.resource.indexOf('.nvue') !== -1 ||
normalizePath(module.resource).indexOf(mainPath) === 0 // main.js
)) {
return false
}
return true
},
minChunks: 1,
name: 'common/vendor',
chunks: 'all'
}
}
}
}
function baseTest (module) {
if (module.type === 'css/mini-extract') {
return false
}
if (module.resource) {
const resource = normalizePath(module.resource)
if (
resource.indexOf('.vue') !== -1 ||
resource.indexOf('.nvue') !== -1 ||
resource.indexOf(mainPath) === 0 // main.js
) {
return false
}
}
return true
}
function getModuleChunks (module, chunks) {
// webpack5
if ('chunkGraph' in chunks) {
chunks = chunks.chunkGraph.getModuleChunks(module)
}
return chunks
}
// TODO 独立分包
const cacheGroups = {
default: false,
vendors: false,
commons: {
test (module, chunks) {
if (!baseTest(module)) {
return false
}
chunks = getModuleChunks(module, chunks)
const matchSubPackages = findSubPackages(chunks)
const matchSubPackagesCount = matchSubPackages.size
const isMainPackage = ( // 非分包 或 两个及以上分包 或 主包内有使用
matchSubPackagesCount === 0 ||
matchSubPackagesCount > 1 ||
(
matchSubPackagesCount === 1 &&
hasMainPackage(chunks)
) ||
(
matchSubPackagesCount === 1 &&
hasMainPackageComponent(module, matchSubPackages.values().next().value)
)
)
if (isMainPackage && process.env.UNI_OPT_TRACE) {
console.log('main', module.resource, chunks.map(chunk => chunk.name))
}
return isMainPackage
},
minSize: 0,
minChunks: 1,
name: 'common/vendor',
chunks: 'all'
}
}
const findSubPackages = function (chunks) {
return chunks.reduce((pkgs, item) => {
const name = normalizePath(item.name)
const pkgRoot = normalSubPackageRoots.find(root => name.indexOf(root) === 0)
pkgRoot && pkgs.add(pkgRoot)
return pkgs
}, new Set())
}
const hasMainPackage = function (chunks) {
return chunks.find(item => !subPackageRoots.find(root => item.name.indexOf(root) === 0))
}
const hasMainPackageComponent = function (module, subPackageRoot) {
if (module.resource && module.reasons) {
for (let index = 0; index < module.reasons.length; index++) {
const m = module.reasons[index]
if (m.module && m.module.resource) {
const resource = normalizePath(m.module.resource)
if (
resource.indexOf('.vue') !== -1 ||
resource.indexOf('.nvue') !== -1
) {
if (resource.indexOf(subPackageRoot) === -1) {
if (process.env.UNI_OPT_TRACE) {
console.log('move module to main chunk:', module.resource,
'from', subPackageRoot, 'for component in main package:', resource)
}
// 独立分包除外
const independentRoot = independentSubpackageRoots.find(root => resource.indexOf(root) >= 0)
if (!independentRoot) {
return true
}
}
} else {
return hasMainPackageComponent(m.module, subPackageRoot)
}
}
}
}
return false
}
const subPackageRoots = Object.keys(process.UNI_SUBPACKAGES).map(root => root + '/')
Object.keys(process.UNI_SUBPACKAGES).forEach(root => {
(function (root) {
cacheGroups[root + '/commons'] = {
test (module, chunks) {
if (!baseTest(module)) {
return false
}
chunks = getModuleChunks(module, chunks)
const matchSubPackages = findSubPackages(chunks)
if (
matchSubPackages.size === 1 &&
matchSubPackages.has(root + '/') &&
!hasMainPackage(chunks) &&
!hasMainPackageComponent(module, matchSubPackages.values().next().value)
) {
if (process.env.UNI_OPT_TRACE) {
console.log(root, module.resource, chunks.map(chunk => chunk.name))
}
return true
}
},
minSize: 0,
minChunks: 1,
name: normalizePath(path.join(root, 'common/vendor')),
chunks: 'all'
}
})(root)
})
return {
chunks (chunk) { // 防止 node_modules 内 vue 组件被 split
return chunk.name.indexOf('node-modules') !== 0
},
cacheGroups
}
}
+119
View File
@@ -0,0 +1,119 @@
const fs = require('fs')
const path = require('path')
const {
pathToGlob
} = require('@dcloudio/uni-cli-shared/lib/util')
let partialIdentifier = false
module.exports = {
getPartialIdentifier () {
if (!partialIdentifier) {
partialIdentifier = {
UNI_COMPILER_VERSION: require('../package.json').version
}
Object.keys(process.env).forEach(name => {
if (name.indexOf('UNI_') === 0) {
partialIdentifier[name] = process.env[name]
}
})
}
return partialIdentifier
},
getAutomatorCode () {
const automator = `@dcloudio/uni-${process.env.UNI_SUB_PLATFORM || process.env.UNI_PLATFORM}/dist/automator`
return process.env.UNI_AUTOMATOR_WS_ENDPOINT ? `import '${automator}';` : ''
},
getWatchOptions () {
return {
ignored: [
pathToGlob(path.resolve(process.env.UNI_INPUT_DIR), '*.md'),
path.resolve(process.env.UNI_INPUT_DIR, '.hbuilderx'),
path.resolve(process.env.UNI_INPUT_DIR, '.editorconfig'),
path.resolve(process.env.UNI_INPUT_DIR, '.gitignore'),
path.resolve(process.env.UNI_INPUT_DIR, 'LICENSE'),
path.resolve(process.env.UNI_INPUT_DIR, 'unpackage'),
path.resolve(process.env.UNI_INPUT_DIR, 'uniCloud-aliyun'),
path.resolve(process.env.UNI_INPUT_DIR, 'uniCloud-tcb'),
path.resolve(process.env.UNI_INPUT_DIR, 'uniCloud-alipay'),
path.resolve(process.env.UNI_INPUT_DIR, 'uniCloud-dcloud'),
path.resolve(process.env.UNI_INPUT_DIR, 'cloudfunctions-aliyun'),
path.resolve(process.env.UNI_INPUT_DIR, 'cloudfunctions-tcb')
]
}
},
getTsLoadOptions () {
const {
isInHBuilderX // 在 HBuilderX 的插件中
} = require('@dcloudio/uni-cli-shared')
const userTsConfigJson = path.resolve(process.env.UNI_INPUT_DIR, 'tsconfig.json')
const defaultTsConfigJson = path.resolve(process.env.UNI_CLI_CONTEXT, 'tsconfig.json')
const tsConfigJsonFile = fs.existsSync(userTsConfigJson) ? userTsConfigJson : defaultTsConfigJson
const context = isInHBuilderX ? process.env.UNI_INPUT_DIR : process.env.UNI_CLI_CONTEXT
function resolveModule (dir) {
return path.resolve(process.env.UNI_CLI_CONTEXT, './node_modules', dir)
}
return {
context,
configFile: tsConfigJsonFile,
compilerOptions: {
baseUrl: context,
typeRoots: [
resolveModule('@dcloudio/types'),
resolveModule('@types'),
path.resolve(process.env.UNI_CLI_CONTEXT, 'types')
],
types: [
'uni-app',
'uni-app-vue2',
'webpack-env'
],
paths: {
'@/*': [
path.join(process.env.UNI_INPUT_DIR, '*')
],
vue: [
resolveModule('vue')
],
vuex: [
resolveModule('vuex')
],
'vue-class-component': [
resolveModule('vue-class-component')
],
'vue-property-decorator': [
resolveModule('vue-property-decorator')
],
tslib: [
resolveModule('tslib')
],
'mpvue-page-factory': [
resolveModule('@dcloudio/vue-cli-plugin-uni/packages/mpvue-page-factory')
],
'@vue/composition-api': [
resolveModule('@dcloudio/vue-cli-plugin-uni/packages/@vue/composition-api')
],
'@dcloudio/uni-app': [
resolveModule('@dcloudio/uni-app')
]
}
},
errorFormatter (error, colors) {
const messageColor = error.severity === 'warning' ? colors.bold.yellow : colors.bold.red
const filePath = path.relative(process.env.UNI_INPUT_DIR, error.file).replace('.vue.ts', '.vue')
if (error.code === 2307 && error.content.includes('.vue')) {
error.content = error.content.replace('Cannot find module ', '') +
' script 节点必须使用 lang="ts",文档参考地址:https://uniapp.dcloud.io/frame?id=vue-ts'
}
return messageColor(
`[tsl] ERROR at ${filePath}:${error.line}
TS${error.code}:${error.content}`
)
}
}
}
}
+60
View File
@@ -0,0 +1,60 @@
const vueLoader = require('@dcloudio/uni-cli-shared/lib/vue-loader')
const {
getPartialIdentifier
} = require('./util')
module.exports = function modifyVueLoader (webpackConfig, loaderOptions, compilerOptions, api) {
// vue-loader options
const cacheConfig = {
cacheDirectory: false,
cacheIdentifier: false
}
if (process.env.UNI_USING_CACHE) {
Object.assign(cacheConfig, api.genCacheConfig(
'vue-template-compiler/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
))
}
webpackConfig.module
.rule('vue')
.test(vueLoader.test)
.use('vue-loader')
.loader(vueLoader.loader)
.tap(options => Object.assign(options, vueLoader.options(loaderOptions, compilerOptions), cacheConfig))
.end()
// 强制使用vue2,vue3时会使用vue-loader-v16
webpackConfig.plugin('vue-loader').use(require(vueLoader.loader).VueLoaderPlugin)
// h5 框架需要使用 scoped 样式,其他平台编译时识别是否 nvue 文件且注入 flex 相关样式
if (process.env.UNI_PLATFORM === 'h5') {
webpackConfig.module
.rule('vue')
.use('uniapp-h5-style-scoped')
.loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-scoped-loader'))
} else {
webpackConfig.module
.rule('vue')
.use('uniapp-nvue-style-loader')
.loader(require.resolve('@dcloudio/webpack-uni-mp-loader/lib/style.js'))
}
// 是否启用 cache
if (process.env.UNI_USING_CACHE) {
webpackConfig.module
.rule('vue')
.use('cache-loader')
.tap(options => Object.assign(options, api.genCacheConfig(
'vue-loader/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
)))
} else {
webpackConfig.module
.rule('vue')
.uses
.delete('cache-loader')
}
}