提交 2b3ee86f 编写于 作者: Q qiang

Merge branch 'v3' of github.com:dcloudio/uni-app into v3

......@@ -21,6 +21,17 @@ const {
getCurrentPages
} = require('uni-platform/service/index')
// 与微信JS-SDK同名的方法
// const sameNameApis = ['setClipboardData', 'getClipboardData', 'onUserCaptureScreen', 'openBluetoothAdapter', 'startBluetoothDevicesDiscovery', 'onBluetoothDeviceFound', 'stopBluetoothDevicesDiscovery', 'onBluetoothAdapterStateChange', 'getConnectedBluetoothDevices', 'getBluetoothDevices', 'getBluetoothAdapterState', 'closeBluetoothAdapter', 'writeBLECharacteristicValue', 'readBLECharacteristicValue', 'onBLEConnectionStateChange', 'onBLECharacteristicValueChange', 'notifyBLECharacteristicValueChange', 'getBLEDeviceServices', 'getBLEDeviceCharacteristics', 'createBLEConnection', 'closeBLEConnection', 'onBeaconServiceChange', 'onBeaconUpdate', 'getBeacons', 'startBeaconDiscovery', 'stopBeaconDiscovery', 'chooseImage', 'previewImage', 'getNetworkType', 'onNetworkStatusChange', 'openLocation', 'getLocation']
// 默认会被iOS企业微信替换的方法
const sameNameApis = ['chooseImage']
sameNameApis.forEach(item => {
Object.defineProperty(uni, item, {
writable: false,
configurable: false
})
})
global.uni = uni
global.wx = global.uni
......@@ -42,4 +53,4 @@ Vue.config.errorHandler = function (err, vm, info) {
initVue(Vue)
require('uni-platform/components')
require('uni-components')
require('uni-components')
......@@ -1079,6 +1079,18 @@ function handleEvent (event) {
handlerCtx.$parent.$parent
) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
handlerCtx = handlerCtx.$parent.$parent;
}
if (methodName === '$emit') {
handlerCtx.$emit.apply(handlerCtx,
processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
));
return
}
const handler = handlerCtx[methodName];
if (!isFn(handler)) {
......
const fs = require('fs')
const path = require('path')
const crypto = require('crypto')
/**
* 1.page-loader 缓存基础的 app.json page.json project.config.json
* 2.main-loader 缓存 app.json 中的 usingComponents 节点
* 3.script-loader 修改缓存 usingComponents 节点
* 5.webpack plugin 中获取被修改的 page.json,component.json 并 emitFile
*/
const jsonFileMap = new Map()
let jsonFileMap = new Map()
const changedJsonFileSet = new Set()
const componentSet = new Set()
let componentSet = new Set()
const pageSet = new Set()
let pageSet = new Set()
let globalUsingComponents = Object.create(null)
let appJsonUsingComponents = Object.create(null)
......@@ -228,6 +231,27 @@ function getSpecialMethods (name) {
return componentSpecialMethods[name] || []
}
const pagesJsonPath = path.resolve(process.env.UNI_INPUT_DIR, 'pages.json')
const cacheTypes = ['babel-loader', 'css-loader', 'uni-template-compiler', 'vue-loader']
function clearCache () {
const fsExtra = require('fs-extra')
cacheTypes.forEach(cacheType => {
fsExtra.emptyDirSync(path.resolve(
process.env.UNI_CLI_CONTEXT,
'node_modules/.cache/' + cacheType + '/' + process.env.UNI_PLATFORM
))
})
}
function digest (str) {
return crypto
.createHash('md5')
.update(str)
.digest('hex')
}
module.exports = {
getPageSet () {
return pageSet
......@@ -235,6 +259,62 @@ module.exports = {
getJsonFileMap () {
return jsonFileMap
},
// 先简单处理,该方案不好,
// 后续为 pages-loader 增加 cache-loader,
// 然后其他修改 json 的地方也要定制 cache-loader
store () {
const filepath = path.resolve(
process.env.UNI_CLI_CONTEXT,
'node_modules/.cache/uni-pages-loader/' + process.env.UNI_PLATFORM,
digest(process.env.UNI_INPUT_DIR) + '.json'
)
const files = Array.from(jsonFileMap.entries())
const pages = Array.from(pageSet)
const components = Array.from(componentSet)
const methods = componentSpecialMethods
fs.writeFileSync(filepath, JSON.stringify({
mtimeMs: fs.statSync(pagesJsonPath).mtimeMs,
files,
pages,
components,
methods,
globalUsingComponents,
appJsonUsingComponents
}))
},
restore () {
const filepath = path.resolve(
process.env.UNI_CLI_CONTEXT,
'node_modules/.cache/uni-pages-loader/' + process.env.UNI_PLATFORM,
digest(process.env.UNI_INPUT_DIR) + '.json'
)
if (!fs.existsSync(filepath)) {
try {
clearCache()
} catch (e) {}
return
}
const mtimeMs = fs.statSync(pagesJsonPath).mtimeMs
const jsonCache = require(filepath)
if (jsonCache.mtimeMs !== mtimeMs) {
try {
clearCache()
} catch (e) {}
return
}
jsonFileMap = new Map(jsonCache.files)
pageSet = new Set(jsonCache.pages)
componentSet = new Set(jsonCache.components)
componentSpecialMethods = jsonCache.methods
globalUsingComponents = jsonCache.globalUsingComponents
appJsonUsingComponents = jsonCache.appJsonUsingComponents
// restore 时,所有 file 均触发 change
for (let name of jsonFileMap.keys()) {
changedJsonFileSet.add(name)
}
return true
},
getJsonFile,
getPagesJson,
getComponentSet,
......
......@@ -1471,6 +1471,18 @@ function handleEvent (event) {
handlerCtx.$parent.$parent
) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
handlerCtx = handlerCtx.$parent.$parent;
}
if (methodName === '$emit') {
handlerCtx.$emit.apply(handlerCtx,
processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
));
return
}
const handler = handlerCtx[methodName];
if (!isFn(handler)) {
......@@ -1763,7 +1775,7 @@ function handleRef (ref) {
if (refName) {
this.$vm.$refs[refName] = ref.$vm || ref;
} else if (refInForName) {
this.$vm.$refs[refInForName] = [ref.$vm || ref];
(this.$vm.$refs[refInForName] || (this.$vm.$refs[refInForName] = [])).push(ref.$vm || ref);
}
}
......@@ -2022,8 +2034,14 @@ function parseComponent (vueComponentOptions) {
mixins: initBehaviors(vueOptions, initBehavior),
data: initData(vueOptions, Vue.prototype),
props,
didMount () {
initVm.call(this, VueComponent);
didMount () {
if (my.dd) { // 钉钉小程序底层基础库有 bug,组件嵌套使用时,在 didMount 中无法及时调用 props 中的方法
setTimeout(() => {
initVm.call(this, VueComponent);
}, 4);
} else {
initVm.call(this, VueComponent);
}
initSpecialMethods(this);
......
......@@ -1216,6 +1216,18 @@ function handleEvent (event) {
handlerCtx.$parent.$parent
) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
handlerCtx = handlerCtx.$parent.$parent;
}
if (methodName === '$emit') {
handlerCtx.$emit.apply(handlerCtx,
processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
));
return
}
const handler = handlerCtx[methodName];
if (!isFn(handler)) {
......@@ -1507,23 +1519,29 @@ function parseComponent (vueOptions) {
const componentOptions = parseBaseComponent(vueOptions, {
isPage,
initRelation
});
});
// 关于百度小程序生命周期的说明(组件作为页面时):
// lifetimes:attached --> methods:onShow --> methods:onLoad --> methods:onReady
// 这里在强制将onShow挪到onLoad之后触发,另外一处修改在page-parser.js
const oldAttached = componentOptions.lifetimes.attached;
componentOptions.lifetimes.attached = function attached () {
oldAttached.call(this);
if (isPage.call(this)) { // 百度 onLoad 在 attached 之前触发
// 百度 当组件作为页面时 pageinstancce 不是原来组件的 instance
this.pageinstance.$vm = this.$vm;
if (hasOwn(this.pageinstance, '_$args')) {
this.$vm.$mp.query = this.pageinstance._$args;
this.$vm.__call_hook('onLoad', this.pageinstance._$args);
this.$vm.__call_hook('onLoad', this.pageinstance._$args);
this.$vm.__call_hook('onShow');
delete this.pageinstance._$args;
}
// TODO 3.105.17以下基础库内百度 Component 作为页面时,methods 中的 onShow 不触发
!newLifecycle && this.$vm.__call_hook('onShow');
} else {
// 百度小程序组件不触发methods内的onReady
if (this.$vm) {
this.$vm._isMounted = true;
this.$vm.__call_hook('mounted');
}
}
};
......@@ -1590,13 +1608,21 @@ function parsePage (vuePageOptions) {
initRelation
});
// 纠正百度小程序生命周期methods:onShow在methods:onLoad之前触发的问题
pageOptions.methods.onShow = function onShow () {
if (this.$vm && this.$vm.$mp.query) {
this.$vm.__call_hook('onShow');
}
};
pageOptions.methods.onLoad = function onLoad (args) {
// 百度 onLoad 在 attached 之前触发,先存储 args, 在 attached 里边触发 onLoad
if (this.$vm) {
this.$vm.$mp.query = args;
this.$vm.__call_hook('onLoad', args);
} else {
this.pageinstance._$args = args;
if (this.$vm) {
this.$vm.$mp.query = args;
this.$vm.__call_hook('onLoad', args);
this.$vm.__call_hook('onShow');
} else {
this.pageinstance._$args = args;
}
};
......
......@@ -1134,6 +1134,18 @@ function handleEvent (event) {
handlerCtx.$parent.$parent
) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
handlerCtx = handlerCtx.$parent.$parent;
}
if (methodName === '$emit') {
handlerCtx.$emit.apply(handlerCtx,
processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
));
return
}
const handler = handlerCtx[methodName];
if (!isFn(handler)) {
......@@ -1214,6 +1226,11 @@ function parseBaseApp (vm, {
if (this.$vm) { // 已经初始化过了,主要是为了百度,百度 onShow 在 onLaunch 之前
return
}
{
if (!wx.canIUse('nextTick')) { // 事实 上2.2.3 即可,简单使用 2.3.0 的 nextTick 判断
console.error('当前微信基础库版本过低,请将 微信开发者工具-详情-项目设置-调试基础库版本 更换为`2.3.0`以上');
}
}
this.$vm = vm;
......@@ -1339,6 +1356,13 @@ function parseBaseComponent (vueComponentOptions, {
addGlobalClass: true
};
{
// 微信 multipleSlots 部分情况有 bug,导致内容顺序错乱 如 u-list,提供覆盖选项
if (vueOptions['mp-weixin'] && vueOptions['mp-weixin']['options']) {
Object.assign(options, vueOptions['mp-weixin']['options']);
}
}
const componentOptions = {
options,
data: initData(vueOptions, Vue.prototype),
......
......@@ -1226,6 +1226,18 @@ function handleEvent (event) {
handlerCtx.$parent.$parent
) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
handlerCtx = handlerCtx.$parent.$parent;
}
if (methodName === '$emit') {
handlerCtx.$emit.apply(handlerCtx,
processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
));
return
}
const handler = handlerCtx[methodName];
if (!isFn(handler)) {
......
......@@ -1074,6 +1074,18 @@ function handleEvent (event) {
handlerCtx.$parent.$parent
) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
handlerCtx = handlerCtx.$parent.$parent;
}
if (methodName === '$emit') {
handlerCtx.$emit.apply(handlerCtx,
processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
));
return
}
const handler = handlerCtx[methodName];
if (!isFn(handler)) {
......@@ -1281,7 +1293,7 @@ function parseBaseComponent (vueComponentOptions, {
};
{
// 微信multipleSlots 部分情况有 bug,导致内容顺序错乱 如 u-list,提供覆盖选项
// 微信 multipleSlots 部分情况有 bug,导致内容顺序错乱 如 u-list,提供覆盖选项
if (vueOptions['mp-weixin'] && vueOptions['mp-weixin']['options']) {
Object.assign(options, vueOptions['mp-weixin']['options']);
}
......
......@@ -132,6 +132,17 @@ at ${resourcePath}.vue:1`)
* ...暂时使用方案1
*/
if (options.emitFile) {
// cache
if (process.env.UNI_USING_CACHE) {
const oldEmitFile = options.emitFile
process.UNI_CACHE_TEMPLATES = {}
options.emitFile = function emitFile (name, content) {
const absolutePath = path.resolve(process.env.UNI_OUTPUT_DIR, name)
process.UNI_CACHE_TEMPLATES[absolutePath] = content
oldEmitFile(name, content)
}
}
if (options.updateSpecialMethods) {
options.updateSpecialMethods(resourcePath, [...res.specialMethods])
}
......
......@@ -96,7 +96,7 @@ const rules = [{
babelrc: false
}
},
jsPreprocessorLoader
jsPreprocessorLoader
],
exclude (modulePath) {
return excludeModuleReg.test(modulePath) && modulePath.indexOf('@dcloudio') === -1
......
......@@ -6,7 +6,7 @@ const {
isInHBuilderX
} = require('@dcloudio/uni-cli-shared')
// override
// nvue override
moduleAlias.addAlias('weex-styler', path.resolve(__dirname, 'packages/weex-styler'))
moduleAlias.addAlias('weex-template-compiler', path.resolve(__dirname, 'packages/weex-template-compiler'))
moduleAlias.addAlias('./compileTemplate', path.resolve(__dirname,
......@@ -19,6 +19,20 @@ moduleAlias.addAlias('./templateLoader', (fromPath, request, alias) => {
}
return request
})
// vue cache
if ( // 非 h5 ,非 v3,非 native
process.env.UNI_PLATFORM !== 'h5' &&
!process.env.UNI_USING_V3 &&
!process.env.UNI_USING_NATIVE
) {
moduleAlias.addAlias('./loaders/pitcher', (fromPath, request, alias) => {
if (fromPath.indexOf('vue-loader') !== -1) {
return path.resolve(__dirname, 'packages/vue-loader/lib/loaders/pitcher')
}
return request
})
}
if (isInHBuilderX) {
moduleAlias.addAlias('typescript', path.resolve(process.env.UNI_HBUILDERX_PLUGINS,
'compile-typescript/node_modules/typescript'))
......
const qs = require('querystring')
const loaderUtils = require('loader-utils')
const hash = require('hash-sum')
const selfPath = require.resolve('vue-loader/lib/index')
const templateLoaderPath = require.resolve('vue-loader/lib/loaders/templateLoader')
const stylePostLoaderPath = require.resolve('vue-loader/lib/loaders/stylePostLoader')
const isESLintLoader = l => /(\/|\\|@)eslint-loader/.test(l.path)
const isNullLoader = l => /(\/|\\|@)null-loader/.test(l.path)
const isCSSLoader = l => /(\/|\\|@)css-loader/.test(l.path)
const isCacheLoader = l => /(\/|\\|@)cache-loader/.test(l.path)
const isPitcher = l => l.path !== __filename
const isPreLoader = l => !l.pitchExecuted
const isPostLoader = l => l.pitchExecuted
const dedupeESLintLoader = loaders => {
const res = []
let seen = false
loaders.forEach(l => {
if (!isESLintLoader(l)) {
res.push(l)
} else if (!seen) {
seen = true
res.push(l)
}
})
return res
}
const shouldIgnoreCustomBlock = loaders => {
const actualLoaders = loaders.filter(loader => {
// vue-loader
if (loader.path === selfPath) {
return false
}
// cache-loader
if (isCacheLoader(loader)) {
return false
}
return true
})
return actualLoaders.length === 0
}
module.exports = code => code
// This pitching loader is responsible for intercepting all vue block requests
// and transform it into appropriate requests.
module.exports.pitch = function (remainingRequest) {
const options = loaderUtils.getOptions(this)
const { cacheDirectory, cacheIdentifier } = options
const query = qs.parse(this.resourceQuery.slice(1))
let loaders = this.loaders
// if this is a language block request, eslint-loader may get matched
// multiple times
if (query.type) {
// if this is an inline block, since the whole file itself is being linted,
// remove eslint-loader to avoid duplicate linting.
if (/\.vue$/.test(this.resourcePath)) {
loaders = loaders.filter(l => !isESLintLoader(l))
} else {
// This is a src import. Just make sure there's not more than 1 instance
// of eslint present.
loaders = dedupeESLintLoader(loaders)
}
}
// remove self
loaders = loaders.filter(isPitcher)
// do not inject if user uses null-loader to void the type (#1239)
if (loaders.some(isNullLoader)) {
return
}
const genRequest = loaders => {
// Important: dedupe since both the original rule
// and the cloned rule would match a source import request.
// also make sure to dedupe based on loader path.
// assumes you'd probably never want to apply the same loader on the same
// file twice.
// Exception: in Vue CLI we do need two instances of postcss-loader
// for user config and inline minification. So we need to dedupe baesd on
// path AND query to be safe.
const seen = new Map()
const loaderStrings = []
loaders.forEach(loader => {
const identifier = typeof loader === 'string'
? loader
: (loader.path + loader.query)
const request = typeof loader === 'string' ? loader : loader.request
if (!seen.has(identifier)) {
seen.set(identifier, true)
// loader.request contains both the resolved loader path and its options
// query (e.g. ??ref-0)
loaderStrings.push(request)
}
})
return loaderUtils.stringifyRequest(this, '-!' + [
...loaderStrings,
this.resourcePath + this.resourceQuery
].join('!'))
}
// Inject style-post-loader before css-loader for scoped CSS and trimming
if (query.type === `style`) {
const cssLoaderIndex = loaders.findIndex(isCSSLoader)
if (cssLoaderIndex > -1) {
const afterLoaders = loaders.slice(0, cssLoaderIndex + 1)
const beforeLoaders = loaders.slice(cssLoaderIndex + 1)
const request = genRequest([
...afterLoaders,
stylePostLoaderPath,
...beforeLoaders
])
// console.log(request)
return `import mod from ${request}; export default mod; export * from ${request}`
}
}
// for templates: inject the template compiler & optional cache
if (query.type === `template`) {
const path = require('path')
// fixed by xxxxxx
const cacheLoader = cacheDirectory && cacheIdentifier
? [`${require.resolve('cache-loader')}??uni-cache-loader-template-options`]
: []
const preLoaders = loaders.filter(isPreLoader)
const postLoaders = loaders.filter(isPostLoader)
const request = genRequest([
...cacheLoader,
...postLoaders,
templateLoaderPath + `??vue-loader-options`,
...preLoaders
])
// console.log(request)
// the template compiler uses esm exports
return `export * from ${request}`
}
// if a custom block has no other matching loader other than vue-loader itself
// or cache-loader, we should ignore it
if (query.type === `custom` && shouldIgnoreCustomBlock(loaders)) {
return ``
}
// When the user defines a rule that has only resourceQuery but no test,
// both that rule and the cloned rule will match, resulting in duplicated
// loaders. Therefore it is necessary to perform a dedupe here.
const request = genRequest(loaders)
return `import mod from ${request}; export default mod; export * from ${request}`
}
......@@ -2,8 +2,8 @@ const loaderUtils = require('loader-utils')
module.exports = function(content) {
this.cacheable && this.cacheable()
const vueLoaderOptions = this.loaders[0]
if (vueLoaderOptions.ident === 'vue-loader-options') {
const vueLoaderOptions = this.loaders.find(loader => loader.ident === 'vue-loader-options')
if (vueLoaderOptions) {
const params = loaderUtils.parseQuery(this.resourceQuery)
if (params.recyclable) {
Object.assign(vueLoaderOptions.options.compilerOptions, {
......
......@@ -25,8 +25,8 @@ module.exports = (api, options) => {
require('./lib/options')(options)
api.configureWebpack(require('./lib/configure-webpack')(platformOptions, manifestPlatformOptions, options))
api.chainWebpack(require('./lib/chain-webpack')(platformOptions, options))
api.configureWebpack(require('./lib/configure-webpack')(platformOptions, manifestPlatformOptions, options, api))
api.chainWebpack(require('./lib/chain-webpack')(platformOptions, api))
}
module.exports.defaultModes = {
......
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) {
return {
resourceQuery: /type=uni-cache-loader-template/,
use: [{
loader: 'cache-loader',
ident: 'uni-cache-loader-template-options',
options: Object.assign(api.genCacheConfig(
'uni-template-compiler/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
), {
read,
write
})
}]
}
}
}
......@@ -4,11 +4,15 @@ const {
sassLoaderVersion
} = require('@dcloudio/uni-cli-shared/lib/scss')
const {
getPartialIdentifier
} = require('./util')
function resolve (dir) {
return path.resolve(__dirname, '..', dir)
}
module.exports = function chainWebpack (platformOptions, vueOptions) {
module.exports = function chainWebpack (platformOptions, api) {
const {
runByHBuilderX, // 使用 HBuilderX 运行
cssPreprocessOptions
......@@ -48,11 +52,22 @@ module.exports = function chainWebpack (platformOptions, vueOptions) {
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')
}
langRule.oneOf(type)
.use(`uniapp-preprocss`)
.loader(resolve('packages/webpack-preprocess-loader'))
.options(cssPreprocessOptions)
.before('css-loader') // 在 css-loader 之后条件编译一次,避免 import 进来的 css 没有走条件编译
if (loader) { // 在 scss,less,stylus 之前先条件编译一次
langRule.oneOf(type)
.use(`uniapp-preprocss-` + lang)
......@@ -79,7 +94,7 @@ module.exports = function chainWebpack (platformOptions, vueOptions) {
})
}
platformOptions.chainWebpack(webpackConfig, vueOptions)
platformOptions.chainWebpack(webpackConfig, api)
// define
webpackConfig
.plugin('uni-define')
......
......@@ -6,6 +6,10 @@ const CopyWebpackPlugin = require('copy-webpack-plugin')
const merge = require('webpack-merge')
const {
getPartialIdentifier
} = require('./util')
function resolve (dir) {
return path.resolve(__dirname, '..', dir)
}
......@@ -14,11 +18,12 @@ function resolveModule (dir) {
return path.resolve(__dirname, '../../..', dir)
}
module.exports = function configureWebpack (platformOptions, manifestPlatformOptions, vueOptions) {
module.exports = function configureWebpack (platformOptions, manifestPlatformOptions, vueOptions, api) {
const {
runByHBuilderX, // 使用 HBuilderX 运行
isInHBuilderX, // 在 HBuilderX 的插件中
hasModule,
getMainEntry,
getPlatformVue,
jsPreprocessOptions,
htmlPreprocessOptions
......@@ -137,13 +142,19 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt
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)) {
if (uses.find(use => use.loader === 'babel-loader')) {
const index = uses.findIndex(use => use.loader === 'cache-loader')
uses.splice(index, 1)
if (process.env.UNI_USING_CACHE) {
Object.assign(uses[index].options, api.genCacheConfig(
'babel-loader/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
))
} else {
uses.splice(index, 1)
}
}
}
}
......@@ -167,14 +178,14 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt
let platformWebpackConfig = platformOptions.webpackConfig
if (typeof platformWebpackConfig === 'function') {
platformWebpackConfig = platformWebpackConfig(webpackConfig, vueOptions)
platformWebpackConfig = platformWebpackConfig(webpackConfig, api)
}
// 移除 node_modules 目录,避免受路径上的 node_modules 影响
webpackConfig.resolve.modules = webpackConfig.resolve.modules.filter(module => module !==
'node_modules')
const plugins = [
new CopyWebpackPlugin(getCopyWebpackPluginOptions(manifestPlatformOptions, vueOptions))
new CopyWebpackPlugin(getCopyWebpackPluginOptions(manifestPlatformOptions))
]
if (process.UNI_SCRIPT_ENV && Object.keys(process.UNI_SCRIPT_ENV).length) {
......@@ -196,6 +207,26 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt
}))
}
let useBuiltIns = 'entry'
if (process.env.UNI_PLATFORM === 'h5') { // 兼容旧版本 h5
useBuiltIns = 'usage'
try {
const babelConfig = require(path.resolve(process.env.UNI_CLI_CONTEXT, 'babel.config.js'))
useBuiltIns = babelConfig.presets[0][1].useBuiltIns
} catch (e) {}
}
const statCode = process.env.UNI_USING_STAT ? `import '@dcloudio/uni-stat';` : ''
let beforeCode = ''
if (process.env.UNI_PLATFORM === 'h5') {
beforeCode = (useBuiltIns === 'entry' ? `import '@babel/polyfill';` : '') +
`import 'uni-pages';import 'uni-${process.env.UNI_PLATFORM}';`
} else {
beforeCode = `import 'uni-pages';`
}
const rules = [{
test: path.resolve(process.env.UNI_INPUT_DIR, 'pages.json'),
use: [{
......@@ -205,6 +236,18 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt
}],
type: 'javascript/auto'
},
{
test: path.resolve(process.env.UNI_INPUT_DIR, getMainEntry()),
// resourceQuery: /type=wrapper/,
use: [{
loader: 'wrap-loader',
options: {
before: [
beforeCode + statCode
]
}
}]
},
{
resourceQuery: /vue&type=template/,
use: [{
......
const fs = require('fs')
const path = require('path')
const mkdirp = require('mkdirp')
// 初始化环境变量
const defaultInputDir = '../../../../src'
......@@ -26,6 +28,10 @@ process.env.UNI_CLI_CONTEXT = path.resolve(__dirname, '../../../../')
process.UNI_LIBRARIES = process.UNI_LIBRARIES || ['@dcloudio/uni-ui']
if (process.env.NODE_ENV === 'production') { // 发行模式,不启用 cache
delete process.env.UNI_USING_CACHE
}
const {
isSupportSubPackages,
runByHBuilderX,
......@@ -126,6 +132,8 @@ if (process.env.UNI_PLATFORM === 'app-plus') {
isNVueCompiler = true // v3 目前仅支持 uni-app 模式
}
if (platformOptions.renderer === 'native') {
// 纯原生目前不提供 cache
delete process.env.UNI_USING_CACHE
process.env.UNI_USING_NATIVE = true
process.env.UNI_USING_V8 = true
process.env.UNI_OUTPUT_TMP_DIR = ''
......@@ -249,6 +257,14 @@ moduleAlias.addAlias('vue-template-compiler', '@dcloudio/vue-cli-plugin-uni/pack
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')
if (process.env.UNI_PLATFORM === 'mp-toutiao') {
// !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) {
......@@ -265,8 +281,25 @@ if (runByHBuilderX) {
}
}
console.log(`正在编译中...`)
if (
process.env.UNI_USING_CACHE &&
process.env.UNI_PLATFORM !== 'h5' &&
!process.env.UNI_USING_V3 &&
!process.env.UNI_USING_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()
}
}
runByHBuilderX && console.log(`正在编译中...`)
module.exports = {
manifestPlatformOptions: platformOptions
}
}
......@@ -4,9 +4,11 @@ const path = require('path')
const {
getMainEntry,
getH5Options,
getPlatformCompiler
getPlatformCssnano
} = require('@dcloudio/uni-cli-shared')
const modifyVueLoader = require('../vue-loader')
const WebpackHtmlAppendPlugin = require('../../packages/webpack-html-append-plugin')
function resolve (dir) {
......@@ -61,18 +63,6 @@ if (devServer && Object.keys(devServer).length) {
module.exports = {
vueConfig,
webpackConfig (webpackConfig) {
let useBuiltIns = 'usage'
const statCode = process.env.UNI_USING_STAT ? `import '@dcloudio/uni-stat';` : ''
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';` : '') +
`import 'uni-pages';import 'uni-${process.env.UNI_PLATFORM}';`
return {
devtool: process.env.NODE_ENV === 'production' ? false : 'source-map',
resolve: {
......@@ -84,16 +74,6 @@ module.exports = {
},
module: {
rules: [{
test: path.resolve(process.env.UNI_INPUT_DIR, getMainEntry()),
use: [{
loader: 'wrap-loader',
options: {
before: [
beforeCode + statCode
]
}
}]
}, {
test: /App\.vue$/,
use: {
loader: 'wrap-loader',
......@@ -104,7 +84,7 @@ module.exports = {
}, {
resourceQuery: /vue&type=template/,
use: [{
loader: resolve('packages/webpack-uni-app-loader/filter-modules-template.js')
loader: resolve('packages/h5-vue-template-loader')
}]
}, {
resourceQuery: [/lang=wxs/, /blockType=wxs/],
......@@ -121,7 +101,7 @@ module.exports = {
plugins
}
},
chainWebpack (webpackConfig) {
chainWebpack (webpackConfig, api) {
webpackConfig.plugins.delete('copy')
if (!process.env.UNI_OPT_PREFETCH) {
......@@ -130,32 +110,56 @@ module.exports = {
if (!process.env.UNI_OPT_PRELOAD) {
webpackConfig.plugins.delete('preload-index')
}
// Vue
webpackConfig.module
.rule('vue')
.test([/\.vue$/, /\.nvue$/])
.use('vue-loader')
.tap(options => Object.assign(options, {
compiler: getPlatformCompiler(),
compilerOptions: require('./compiler-options'),
cacheDirectory: false,
cacheIdentifier: false
}))
.end()
.use('uniapp-custom-block-loader')
.loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-custom-block-loader'))
.options({
compiler: getPlatformCompiler()
})
.end()
.use('uniapp-scoped')
.loader(resolve('packages/webpack-scoped-loader'))
.end()
.uses
.delete('cache-loader')
modifyVueLoader(webpackConfig, require('./compiler-options'), api)
if (process.env.NODE_ENV === 'production') {
require('./cssnano-options')(webpackConfig)
const module = webpackConfig.module
// TODO 临时 hack calc:false 看看 vue cli 后续是否开放 cssnano 的配置
const cssnanoOptions = {
sourceMap: false,
plugins: [require('cssnano')({
preset: ['default', getPlatformCssnano()]
})]
}
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)
}
}
}
......@@ -9,13 +9,14 @@ const {
parseEntry,
getMainEntry,
getPlatformExts,
getPlatformCompiler,
getPlatformCssnano
} = require('@dcloudio/uni-cli-shared')
const modifyVueLoader = require('./vue-loader')
const {
isUnaryTag
} = require('./util')
createTemplateCacheLoader
} = require('./cache-loader')
function createUniMPPlugin () {
if (process.env.UNI_USING_COMPONENTS) {
......@@ -27,11 +28,6 @@ function createUniMPPlugin () {
}
function getProvides () {
if (process.env.UNI_USING_V3) {
return {
'__f__': [path.resolve(__dirname, 'format-log.js'), 'default']
}
}
const uniPath = require.resolve('@dcloudio/uni-' + process.env.UNI_PLATFORM)
const provides = {
'uni': [uniPath, 'default']
......@@ -47,7 +43,7 @@ function getProvides () {
process.env.UNI_PLATFORM === 'app-plus' &&
process.env.UNI_USING_V8
) {
provides['__f__'] = [path.resolve(__dirname, 'format-log.js'), 'default']
provides['__f__'] = [path.resolve(__dirname, 'format-log.js'), 'default']
provides['crypto'] = [path.resolve(__dirname, 'crypto.js'), 'default']
}
......@@ -66,7 +62,7 @@ module.exports = {
vueConfig: {
parallel: false
},
webpackConfig (webpackConfig) {
webpackConfig (webpackConfig, api) {
if (!webpackConfig.optimization) {
webpackConfig.optimization = {}
}
......@@ -74,7 +70,7 @@ module.exports = {
webpackConfig.optimization.noEmitOnErrors = false
webpackConfig.optimization.runtimeChunk = {
name: process.env.UNI_USING_V3 ? 'app-config' : 'common/runtime'
name: 'common/runtime'
}
webpackConfig.optimization.splitChunks = require('./split-chunks')()
......@@ -99,23 +95,10 @@ module.exports = {
}
}
if (process.env.UNI_USING_V3) {
devtool = false
}
const statCode = process.env.UNI_USING_STAT ? `import '@dcloudio/uni-stat';` : ''
const beforeCode = `import 'uni-pages';`
return {
devtool,
mode: process.env.NODE_ENV,
entry () {
if (process.env.UNI_USING_V3) {
return {
'app-service': path.resolve(process.env.UNI_INPUT_DIR, getMainEntry())
}
}
return process.UNI_ENTRY
},
output: {
......@@ -138,13 +121,6 @@ module.exports = {
rules: [{
test: path.resolve(process.env.UNI_INPUT_DIR, getMainEntry()),
use: [{
loader: 'wrap-loader',
options: {
before: [
beforeCode + statCode
]
}
}, {
loader: '@dcloudio/webpack-uni-mp-loader/lib/main'
}]
}, {
......@@ -157,7 +133,7 @@ module.exports = {
use: [{
loader: '@dcloudio/webpack-uni-mp-loader/lib/template'
}]
}, {
}, createTemplateCacheLoader(api), {
resourceQuery: [
/lang=wxs/,
/lang=filter/,
......@@ -178,7 +154,7 @@ module.exports = {
]
}
},
chainWebpack (webpackConfig) {
chainWebpack (webpackConfig, api) {
if (process.env.UNI_PLATFORM === 'mp-baidu') {
webpackConfig.module
.rule('js')
......@@ -186,47 +162,16 @@ module.exports = {
.add(/\.filter\.js$/)
}
const compilerOptions = process.env.UNI_USING_COMPONENTS ? {
isUnaryTag,
preserveWhitespace: false
} : require('./mp-compiler-options')
if (process.env.UNI_USING_V3) {
compilerOptions.service = true
}
const compilerOptions = process.env.UNI_USING_COMPONENTS ? {} : require('./mp-compiler-options')
// disable vue cache-loader
webpackConfig.module
.rule('vue')
.test([/\.vue$/, /\.nvue$/])
.use('vue-loader')
.tap(options => Object.assign(options, {
compiler: getPlatformCompiler(),
compilerOptions,
cacheDirectory: false,
cacheIdentifier: false
}))
.end()
.use('uniapp-custom-block-loader')
.loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-custom-block-loader'))
.options({
compiler: getPlatformCompiler()
})
.end()
.use('uniapp-nvue-loader')
.loader(require.resolve('@dcloudio/webpack-uni-mp-loader/lib/style.js'))
.end()
.uses
.delete('cache-loader')
modifyVueLoader(webpackConfig, compilerOptions, api)
const styleExt = getPlatformExts().style
if (!process.env.UNI_USING_V3) {
webpackConfig.plugin('extract-css')
.init((Plugin, args) => new Plugin({
filename: '[name]' + styleExt
}))
}
webpackConfig.plugin('extract-css')
.init((Plugin, args) => new Plugin({
filename: '[name]' + styleExt
}))
if (
process.env.NODE_ENV === 'production' &&
......
......@@ -9,9 +9,24 @@ function makeMap (str, expectsLowerCase) {
: val => map[val]
}
let partialIdentifier = false
module.exports = {
isUnaryTag: makeMap(
'image,area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' +
'link,meta,param,source,track,wbr'
)
),
getPartialIdentifier () {
if (partialIdentifier) {
return 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
}
}
const {
getPlatformCompiler
} = require('@dcloudio/uni-cli-shared')
const {
isUnaryTag,
getPartialIdentifier
} = require('./util')
module.exports = function modifyVueLoader (webpackConfig, compilerOptions, api) {
// vue-loader options
const cacheConfig = {
cacheDirectory: false,
cacheIdentifier: false
}
const partialIdentifier = {}
if (process.env.UNI_USING_CACHE) {
Object.assign(cacheConfig, api.genCacheConfig(
'vue-template-compiler/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
))
}
webpackConfig.module
.rule('vue')
.test([/\.vue$/, /\.nvue$/])
.use('vue-loader')
.tap(options => Object.assign(options, {
compiler: getPlatformCompiler(),
compilerOptions: Object.assign({
isUnaryTag,
preserveWhitespace: false
}, compilerOptions)
}, cacheConfig))
.end()
.use('uniapp-custom-block-loader')
.loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-custom-block-loader'))
.options({
compiler: getPlatformCompiler()
})
// 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,
partialIdentifier
)))
} else {
webpackConfig.module
.rule('vue')
.uses
.delete('cache-loader')
}
}
{
"name": "@dcloudio/vue-cli-plugin-uni",
"version": "3.0.0-alpha-24020191018029",
"version": "2.0.0-23320190923002",
"description": "uni-app plugin for vue-cli 3",
"main": "index.js",
"repository": {
......@@ -17,12 +17,14 @@
"author": "fxy060608",
"license": "Apache-2.0",
"dependencies": {
"@dcloudio/uni-stat": "^3.0.0-alpha-24020191018029",
"@dcloudio/uni-stat": "^2.0.0-23320190923002",
"buffer-json": "^2.0.0",
"copy-webpack-plugin": "^4.6.0",
"cross-env": "^5.2.0",
"envinfo": "^6.0.1",
"hash-sum": "^1.0.2",
"loader-utils": "^1.1.0",
"mkdirp": "^0.5.1",
"module-alias": "^2.1.0",
"postcss": "^7.0.7",
"postcss-import": "^12.0.1",
......@@ -34,5 +36,5 @@
"wrap-loader": "^0.2.0",
"xregexp": "4.0.0"
},
"gitHead": "6b0d55e296028761e3de4b561c1ad7c5fb7a23e2"
"gitHead": "10184426b19cb76e01c93fb25c982c72887557e8"
}
Copyright (c) Ben Briggs <beneb.info@gmail.com> (http://beneb.info)
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
# [postcss][postcss]-normalize-whitespace
> Normalize whitespace with PostCSS.
## Install
With [npm](https://npmjs.org/package/postcss-normalize-whitespace) do:
```
npm install postcss-normalize-whitespace --save
```
## Example
### Input
```css
h1{
width: calc(10px - ( 100px / var(--test) ))
}
```
### Output
```css
h1{
width: calc(10px - 100px / var(--test))
}
```
## Usage
See the [PostCSS documentation](https://github.com/postcss/postcss#usage) for
examples for your environment.
## Contributors
See [CONTRIBUTORS.md](https://github.com/cssnano/cssnano/blob/master/CONTRIBUTORS.md).
## License
MIT © [Ben Briggs](http://beneb.info)
[postcss]: https://github.com/postcss/postcss
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _postcss = require("postcss");
var _postcssValueParser = require("postcss-value-parser");
var _postcssValueParser2 = _interopRequireDefault(_postcssValueParser);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const atrule = "atrule";
const decl = "decl";
const rule = "rule";
function reduceCalcWhitespaces(node) {
if (node.type === "space") {
node.value = " ";
} else if (node.type === "function") {
node.before = node.after = "";
}
}
function reduceWhitespaces(node) {
if (node.type === "space") {
node.value = " ";
} else if (node.type === "div") {
node.before = node.after = "";
} else if (node.type === "function") {
node.before = node.after = "";
if (node.value.toLowerCase() === "calc") {
_postcssValueParser2.default.walk(node.nodes, reduceCalcWhitespaces);
return false;
}
}
}
exports.default = (0, _postcss.plugin)("postcss-normalize-whitespace", () => {
return css => {
const cache = {};
css.walk(node => {
const { type } = node;
if (~[decl, rule, atrule].indexOf(type) && node.raws.before) {
node.raws.before = node.raws.before.replace(/\s/g, "");
}
if (type === decl) {
// Ensure that !important values do not have any excess whitespace
if (node.important) {
// fixed by xxxxxx 头条小程序 rpx!important 中间必须有空格,否则无法正确转换
node.raws.important = " !important";
}
// Remove whitespaces around ie 9 hack
node.value = node.value.replace(/\s*(\\9)\s*/, "$1");
const value = node.value;
if (cache[value]) {
node.value = cache[value];
} else {
const parsed = (0, _postcssValueParser2.default)(node.value);
const result = parsed.walk(reduceWhitespaces).toString();
// Trim whitespace inside functions & dividers
node.value = result;
cache[value] = result;
}
// Remove extra semicolons and whitespace before the declaration
if (node.raws.before) {
const prev = node.prev();
if (prev && prev.type !== rule) {
node.raws.before = node.raws.before.replace(/;/g, "");
}
}
node.raws.between = ":";
node.raws.semicolon = false;
} else if (type === rule || type === atrule) {
node.raws.between = node.raws.after = "";
node.raws.semicolon = false;
}
});
// Remove final newline
css.raws.after = "";
};
});
module.exports = exports["default"];
\ No newline at end of file
{
"name": "postcss-normalize-whitespace",
"version": "4.0.2",
"description": "Trim whitespace inside and around CSS rules & declarations.",
"main": "dist/index.js",
"files": [
"dist",
"LICENSE-MIT"
],
"scripts": {
"prepublish": "cross-env BABEL_ENV=publish babel src --out-dir dist --ignore /__tests__/"
},
"keywords": [
"css",
"postcss",
"postcss-plugin"
],
"license": "MIT",
"devDependencies": {
"babel-cli": "^6.0.0",
"cross-env": "^5.0.0"
},
"homepage": "https://github.com/cssnano/cssnano",
"author": {
"name": "Ben Briggs",
"email": "beneb.info@gmail.com",
"url": "http://beneb.info"
},
"repository": "cssnano/cssnano",
"dependencies": {
"postcss": "^7.0.0",
"postcss-value-parser": "^3.0.0"
},
"bugs": {
"url": "https://github.com/cssnano/cssnano/issues"
},
"engines": {
"node": ">=6.9.0"
}
}
......@@ -3,8 +3,8 @@ const loaderUtils = require('loader-utils')
module.exports = function (content) {
this.cacheable && this.cacheable()
const vueLoaderOptions = this.loaders[0]
if (vueLoaderOptions.ident === 'vue-loader-options') {
const vueLoaderOptions = this.loaders.find(loader => loader.ident === 'vue-loader-options')
if (vueLoaderOptions) {
const params = loaderUtils.parseQuery(this.resourceQuery)
/* eslint-disable no-mixed-operators */
const filterModules = JSON.parse(params && params['filter-modules'] || '{}')
......
......@@ -82,7 +82,7 @@ function analyzeUsingComponents () {
// pages[name] = usingComponentsMap[name]
// }
// return pages
// }, {})
// }, {})
}
module.exports = function generateJson (compilation) {
......@@ -153,7 +153,7 @@ module.exports = function generateJson (compilation) {
!['app.js', 'manifest.js', 'project.config.js', 'project.swan.js'].includes(jsFile) &&
!compilation.assets[jsFile]
) {
compilation.assets[jsFile] = {
const jsFileAsset = {
size () {
return Buffer.byteLength(EMPTY_COMPONENT, 'utf8')
},
......@@ -161,8 +161,9 @@ module.exports = function generateJson (compilation) {
return EMPTY_COMPONENT
}
}
compilation.assets[jsFile] = jsFileAsset
}
compilation.assets[name] = {
const jsonAsset = {
size () {
return Buffer.byteLength(source, 'utf8')
},
......@@ -170,5 +171,12 @@ module.exports = function generateJson (compilation) {
return source
}
}
compilation.assets[name] = jsonAsset
}
if (process.env.UNI_USING_CACHE && jsonFileMap.size) {
setTimeout(() => {
require('@dcloudio/uni-cli-shared/lib/cache').store()
}, 50)
}
}
......@@ -32,8 +32,8 @@ const filterTagName = getPlatformFilterTag() || ''
module.exports = function (content) {
this.cacheable && this.cacheable()
const vueLoaderOptions = this.loaders[0]
if (vueLoaderOptions.ident === 'vue-loader-options') {
const vueLoaderOptions = this.loaders.find(loader => loader.ident === 'vue-loader-options')
if (vueLoaderOptions) {
const globalUsingComponents = getGlobalUsingComponents()
const realResourcePath = path.relative(process.env.UNI_INPUT_DIR, this.resourcePath)
const resourcePath = normalizeNodeModules(removeExt(realResourcePath) + templateExt)
......
......@@ -25,8 +25,8 @@ module.exports = function (content) {
if (process.env.UNI_USING_COMPONENTS) {
// 向 uni-template-compier 传递 emitFile
const vueLoaderOptions = this.loaders[0]
if (vueLoaderOptions.ident === 'vue-loader-options') {
const vueLoaderOptions = this.loaders.find(loader => loader.ident === 'vue-loader-options')
if (vueLoaderOptions) {
Object.assign(vueLoaderOptions.options.compilerOptions, {
resourcePath: removeExt(realResourcePath) + templateExt,
emitFile: this.emitFile
......@@ -57,8 +57,8 @@ module.exports = function (content) {
cacheCompilerOptions(realResourcePath, compilerOptions)
// 向 vue-loader templateLoader 传递 compilerOptions
const vueLoaderOptions = this.loaders[0]
if (vueLoaderOptions.ident === 'vue-loader-options') {
const vueLoaderOptions = this.loaders.find(loader => loader.ident === 'vue-loader-options')
if (vueLoaderOptions) {
Object.assign(vueLoaderOptions.options.compilerOptions, compilerOptions)
} else {
throw new Error('vue-loader-options parse error')
......
......@@ -11,7 +11,7 @@
"newFeature": true
},
"compileType": "miniprogram",
"libVersion": "",
"libVersion": "2.9.2",
"appid": "touristappid",
"projectname": "",
"condition": {
......
......@@ -485,6 +485,18 @@ export function handleEvent (event) {
handlerCtx.$parent.$parent
) { // mp-weixin,mp-toutiao 抽象节点模拟 scoped slots
handlerCtx = handlerCtx.$parent.$parent
}
if (methodName === '$emit') {
handlerCtx.$emit.apply(handlerCtx,
processEventArgs(
this.$vm,
event,
eventArray[1],
eventArray[2],
isCustom,
methodName
))
return
}
const handler = handlerCtx[methodName]
if (!isFn(handler)) {
......
......@@ -6,11 +6,13 @@ export function getApp () {
return appVm
}
export function getCurrentPages (isAll = false) {
export function getCurrentPages (isAll = false, ignoreError = false) {
const pages = []
const app = getApp()
if (!app) {
console.error('app is not ready')
if (ignoreError) {
console.error('app is not ready')
}
return []
}
const childrenVm = app.$children[0]
......@@ -62,4 +64,4 @@ export default function createApp (vm, routes) {
// initEvents(appVm)
initRouterGuard(appVm, routes)
}
}
......@@ -36,50 +36,33 @@ export function checkIsSoterEnrolledInDevice ({
if (checkAuthMode === 'fingerPrint') {
if (checkIsSupportFingerPrint()) {
const isEnrolled = plus.fingerprint.isKeyguardSecure() && plus.fingerprint.isEnrolledFingerprints()
if (isEnrolled) {
return {
isEnrolled,
errMsg: 'checkIsSoterEnrolledInDevice:ok'
}
} else {
return {
isEnrolled,
errMsg: 'checkIsSoterEnrolledInDevice:ok'
}
}
} else {
return {
isEnrolled: false,
errMsg: 'checkIsSoterEnrolledInDevice:fail not support'
isEnrolled,
errMsg: 'checkIsSoterEnrolledInDevice:ok'
}
}
return {
isEnrolled: false,
errMsg: 'checkIsSoterEnrolledInDevice:fail not support'
}
} else if (checkAuthMode === 'facial') {
if (checkIsSupportFaceID()) {
const faceID = requireNativePlugin('faceID')
const isEnrolled = faceID && faceID.isKeyguardSecure() && faceID.isEnrolledFaceID()
if (isEnrolled) {
return {
isEnrolled,
errMsg: 'checkIsSoterEnrolledInDevice:ok'
}
} else {
return {
isEnrolled,
errMsg: 'checkIsSoterEnrolledInDevice:ok'
}
}
} else {
return {
isEnrolled: false,
errMsg: 'checkIsSoterEnrolledInDevice:fail not support'
isEnrolled,
errMsg: 'checkIsSoterEnrolledInDevice:ok'
}
}
} else {
return {
isEnrolled: false,
errMsg: 'checkIsSoterEnrolledInDevice:fail not support'
}
}
return {
isEnrolled: false,
errMsg: 'checkIsSoterEnrolledInDevice:fail not support'
}
}
export function startSoterAuthentication ({
......@@ -87,6 +70,24 @@ export function startSoterAuthentication ({
challenge = false,
authContent
} = {}, callbackId) {
/*
以手机不支持facial未录入fingerPrint为例
requestAuthModes:['facial','fingerPrint']时,微信小程序返回值里的authMode为"fingerPrint"
requestAuthModes:['fingerPrint','facial']时,微信小程序返回值里的authMode为"fingerPrint"
即先过滤不支持的方式之后再判断是否录入
微信小程序errCode(从企业号开发者中心查到如下文档):
0:识别成功 'startSoterAuthentication:ok'
90001:本设备不支持SOTER 'startSoterAuthentication:fail not support soter'
90002:用户未授权微信使用该生物认证接口 注:APP端暂不支持
90003:请求使用的生物认证方式不支持 'startSoterAuthentication:fail no corresponding mode'
90004:未传入challenge或challenge长度过长(最长512字符)注:APP端暂不支持
90005:auth_content长度超过限制(最长42个字符)注:微信小程序auth_content指纹识别时无效果,faceID暂未测试
90007:内部错误 'startSoterAuthentication:fail auth key update error'
90008:用户取消授权 'startSoterAuthentication:fail cancel'
90009:识别失败 'startSoterAuthentication:fail'
90010:重试次数过多被冻结 'startSoterAuthentication:fail authenticate freeze. please try again later'
90011:用户未录入所选识别方式 'startSoterAuthentication:fail no fingerprint enrolled'
*/
const supportMode = checkIsSupportSoterAuthentication().supportMode
if (supportMode.length === 0) {
return {
......@@ -182,7 +183,7 @@ export function startSoterAuthentication ({
faceID.authenticate({
message: authContent
}, (e) => {
if (e.type === 'success' && e.code === 1) {
if (e.type === 'success' && e.code === 0) {
invoke(callbackId, {
authMode: realAuthMode,
errCode: 0,
......
export * from './base/event-bus'
export * from './context/audio'
export * from './context/audio'
export * from './context/background-audio'
export * from './context/canvas'
export * from './context/operate-map-player'
export * from './context/operate-video-player'
export * from './device/accelerometer'
export * from './device/add-phone-contact'
export * from './device/bluetooth'
export * from './device/brightness'
export * from './device/clipboard'
export * from './device/compass'
export * from './device/get-network-type'
export * from './device/ibeacon'
export * from './device/make-phone-call'
export * from './device/scan-code'
export * from './device/soter-authentication'
export * from './device/system'
export * from './device/vibrate'
export * from './file/file'
export * from './file/open-document'
export * from './location/choose-location'
export * from './location/get-location'
export * from './location/open-location'
export * from './media/audio'
export * from './media/choose-image'
export * from './media/choose-video'
export * from './media/compress-image'
export * from './media/get-image-info'
export * from './media/preview-image'
export * from './media/recorder'
export * from './media/save-image-to-photos-album'
export * from './media/save-video-to-photos-album'
export * from './network/download-file'
export * from './network/request'
export * from './network/socket'
export * from './network/upload-file'
export * from './plugin/get-provider'
export * from './plugin/oauth'
export * from './plugin/payment'
export * from './context/operate-video-player'
export * from './device/accelerometer'
export * from './device/add-phone-contact'
export * from './device/bluetooth'
export * from './device/brightness'
export * from './device/clipboard'
export * from './device/compass'
export * from './device/get-network-type'
export * from './device/ibeacon'
export * from './device/make-phone-call'
export * from './device/scan-code'
export * from './device/soter-authentication'
export * from './device/system'
export * from './device/vibrate'
export * from './file/file'
export * from './file/open-document'
export * from './location/choose-location'
export * from './location/get-location'
export * from './location/open-location'
export * from './media/audio'
export * from './media/choose-image'
export * from './media/choose-video'
export * from './media/compress-image'
export * from './media/get-image-info'
export * from './media/preview-image'
export * from './media/recorder'
export * from './media/save-image-to-photos-album'
export * from './media/save-video-to-photos-album'
export * from './network/download-file'
export * from './network/request'
export * from './network/socket'
export * from './network/upload-file'
export * from './plugin/get-provider'
export * from './plugin/oauth'
export * from './plugin/payment'
export * from './plugin/push'
export * from './plugin/require-native-plugin'
export * from './plugin/require-native-plugin'
export * from './plugin/share'
export * from './plugin/restore-global'
export * from './plugin/sub-nvue'
export * from './route/navigate-back'
export * from './route/navigate-to'
export * from './route/re-launch'
export * from './route/redirect-to'
export * from './plugin/sub-nvue'
export * from './route/navigate-back'
export * from './route/navigate-to'
export * from './route/re-launch'
export * from './route/redirect-to'
export * from './route/switch-tab'
export * from './ui/keyboard'
export * from './ui/navigation-bar'
export * from './ui/popup'
export {
startPullDownRefresh,
stopPullDownRefresh
}
from './ui/pull-down-refresh'
export * from './ui/keyboard'
export * from './ui/navigation-bar'
export * from './ui/popup'
export {
startPullDownRefresh,
stopPullDownRefresh
}
from './ui/pull-down-refresh'
export * from './ui/tab-bar'
export * from './ui/request-component-info'
......@@ -118,13 +118,19 @@ export function showPage ({
animationType: 'pop-in',
animationDuration: 200,
uniNView: {
path: `/${url}.js?from=${getPageId()}&runtime=${runtime}&data=${encodeURIComponent(JSON.stringify(data))}`,
path: `${(typeof process === 'object' && process.env && process.env.VUE_APP_TEMPLATE_PATH) || ''}/${url}.js`,
defaultFontSize: plus_.screen.resolutionWidth / 20,
viewport: plus_.screen.resolutionWidth
}
}
style = Object.assign(defaultStyle, style)
const page = plus_.webview.create('', pageId, style)
const page = plus_.webview.create('', pageId, style, {
extras: {
from: getPageId(),
runtime: runtime,
data
}
})
page.addEventListener('close', onClose)
addEventListener(pageId, message => {
if (typeof onMessage === 'function') {
......@@ -136,4 +142,4 @@ export function showPage ({
})
page.show(style.animationType, style.animationDuration)
return new Page(page)
}
}
......@@ -84,7 +84,7 @@ export function getSystemInfoSync () {
const {
top: windowTop,
bottom: windowBottom
} = getWindowOffset()
} = getWindowOffset(false, true)
windowHeight -= windowTop
windowHeight -= windowBottom
......
......@@ -34,7 +34,7 @@ export function getNetworkType () {
if (connection) {
networkType = connection.type
if (networkType === 'cellular') {
networkType = connection.effectiveType.replace('slow-', '')
networkType = connection.effectiveType && connection.effectiveType.replace('slow-', '')
} else if (!['none', 'wifi'].includes(networkType)) {
networkType = 'unknown'
}
......
import getRealPath from 'uni-platform/helpers/get-real-path'
function _getServiceAddress () {
return window.location.protocol + '//' + window.location.host
}
......@@ -11,7 +9,7 @@ export function getImageInfo ({
invokeCallbackHandler: invoke
} = UniServiceJSBridge
const img = new Image()
const realPath = getRealPath(src)
const realPath = src
img.onload = function () {
invoke(callbackId, {
errMsg: 'getImageInfo:ok',
......@@ -26,4 +24,4 @@ export function getImageInfo ({
})
}
img.src = src
}
}
......@@ -91,8 +91,14 @@ export default function parseComponent (vueComponentOptions) {
mixins: initBehaviors(vueOptions, initBehavior),
data: initData(vueOptions, Vue.prototype),
props,
didMount () {
initVm.call(this, VueComponent)
didMount () {
if (my.dd) { // 钉钉小程序底层基础库有 bug,组件嵌套使用时,在 didMount 中无法及时调用 props 中的方法
setTimeout(() => {
initVm.call(this, VueComponent)
}, 4)
} else {
initVm.call(this, VueComponent)
}
initSpecialMethods(this)
......
......@@ -112,7 +112,7 @@ export function handleRef (ref) {
if (refName) {
this.$vm.$refs[refName] = ref.$vm || ref
} else if (refInForName) {
this.$vm.$refs[refInForName] = [ref.$vm || ref]
(this.$vm.$refs[refInForName] || (this.$vm.$refs[refInForName] = [])).push(ref.$vm || ref)
}
}
......
......@@ -17,9 +17,9 @@ export default function parseComponent (vueOptions) {
initRelation
})
// 关于百度小程序新生命周期(2.0)的说明(组件作为页面时):
// 关于百度小程序生命周期的说明(组件作为页面时):
// lifetimes:attached --> methods:onShow --> methods:onLoad --> methods:onReady
// 这里在新生命周期强制将onShow挪到onLoad之后触发,另外一处修改在page-parser.js
// 这里在强制将onShow挪到onLoad之后触发,另外一处修改在page-parser.js
const oldAttached = componentOptions.lifetimes.attached
componentOptions.lifetimes.attached = function attached () {
oldAttached.call(this)
......
......@@ -25,11 +25,11 @@ export default function parsePage (vuePageOptions) {
initRelation
})
const newLifecycle = swan.canIUse('lifecycle-2-0')
// 纠正百度小程序新生命周期(2.0)methods:onShow在methods:onLoad之前触发的问题
if (newLifecycle) {
delete pageOptions.methods.onShow
// 纠正百度小程序生命周期methods:onShow在methods:onLoad之前触发的问题
pageOptions.methods.onShow = function onShow () {
if (this.$vm && this.$vm.$mp.query) {
this.$vm.__call_hook('onShow')
}
}
pageOptions.methods.onLoad = function onLoad (args) {
......
......@@ -52,7 +52,7 @@ export default function parseBaseApp (vm, {
if (this.$vm) { // 已经初始化过了,主要是为了百度,百度 onShow 在 onLaunch 之前
return
}
if (__PLATFORM__ === 'mp-weixin') {
if (__PLATFORM__ === 'mp-weixin' || __PLATFORM__ === 'mp-qq') {
if (!wx.canIUse('nextTick')) { // 事实 上2.2.3 即可,简单使用 2.3.0 的 nextTick 判断
console.error('当前微信基础库版本过低,请将 微信开发者工具-详情-项目设置-调试基础库版本 更换为`2.3.0`以上')
}
......
......@@ -26,8 +26,8 @@ export default function parseBaseComponent (vueComponentOptions, {
addGlobalClass: true
}
if (__PLATFORM__ === 'mp-weixin') {
// 微信multipleSlots 部分情况有 bug,导致内容顺序错乱 如 u-list,提供覆盖选项
if (__PLATFORM__ === 'mp-weixin' || __PLATFORM__ === 'mp-qq') {
// 微信 multipleSlots 部分情况有 bug,导致内容顺序错乱 如 u-list,提供覆盖选项
if (vueOptions['mp-weixin'] && vueOptions['mp-weixin']['options']) {
Object.assign(options, vueOptions['mp-weixin']['options'])
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册