提交 fe454724 编写于 作者: fxy060608's avatar fxy060608

init v3

上级 5b9bc11b
......@@ -2,3 +2,4 @@ src/core/helpers/html-parser.js
src/platforms/app-plus-nvue/runtime
build/rollup-plugin-require-context
packages/*/packages
packages/uni-cli-shared/template
......@@ -19,20 +19,30 @@ const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd(), {
// 删除 cache 目录
del.sync(['node_modules/.cache'])
let name = 'index'
let filename = ''
let entry = './lib/' + process.env.UNI_PLATFORM + '/main.js'
if (process.env.UNI_PLATFORM === 'h5' && process.env.UNI_UI === 'true') {
entry = './lib/' + process.env.UNI_PLATFORM + '/ui.js'
}
if (process.env.UNI_PLATFORM === 'app-plus' && process.env.UNI_VIEW === 'true') {
name = 'uni'
filename = 'view'
entry = './lib/' + process.env.UNI_PLATFORM + '/view.js'
}
service.run('build', {
name: 'index',
name,
filename,
watch: process.env.UNI_WATCH === 'true',
target: 'lib',
formats: process.env.UNI_WATCH === 'true' ? 'umd' : 'umd-min',
entry
entry,
clean: !process.env.UNI_VIEW
}).then(function () {
if (process.env.UNI_UI !== 'true') {
if (process.env.UNI_UI !== 'true' && process.env.UNI_VIEW !== 'true') {
generateApiManifest(
JSON.parse(JSON.stringify(process.UNI_SERVICE_API_MANIFEST)),
JSON.parse(JSON.stringify(process.UNI_SERVICE_API_PROTOCOL))
......@@ -43,7 +53,7 @@ service.run('build', {
process.exit(1)
})
if (process.env.UNI_WATCH === 'false') {
if (process.env.UNI_PLATFORM === 'h5' && process.env.UNI_WATCH === 'false') {
const packagePath = path.join(__dirname, `../packages/uni-${process.env.UNI_PLATFORM}`)
const packageJsonPath = path.join(packagePath, 'package.json')
del(path.join(packagePath, '{lib,src}'))
......
......@@ -14,20 +14,31 @@ const output = {
const external = []
// if (process.env.UNI_PLATFORM === 'app-plus-nvue') {
// external.push('vue')
// output.globals = {
// vue: 'Vue'
// }
// }
if (process.env.UNI_SERVICE === 'legacy') {
input = 'src/platforms/app-plus-nvue/services/index.legacy.js'
output.file = 'packages/uni-app-plus-nvue/dist/index.legacy.js'
} else {
input = 'src/platforms/app-plus/service/index.js'
output.file = 'packages/uni-app-plus-nvue/dist/index.js'
if (process.env.UNI_PLATFORM === 'app-plus') {
output.file = `packages/uni-app-plus/dist/index.v3.js`
} else {
output.file = `packages/uni-app-plus-nvue/dist/index.js`
}
output.format = 'iife'
output.name = 'serviceContext'
output.banner =
`export function createServiceContext(Vue, weex, plus, __uniConfig, __uniRoutes, UniServiceJSBridge,instanceContext){
var localStorage = plus.storage
var setTimeout = instanceContext.setTimeout
var clearTimeout = instanceContext.clearTimeout
var setInterval = instanceContext.setInterval
var clearTimeout = instanceContext.clearTimeout
var setInterval = instanceContext.setInterval
var clearInterval = instanceContext.clearInterval
`
output.footer =
......@@ -47,23 +58,24 @@ const resolve = dir => path.resolve(__dirname, '../', dir)
module.exports = {
input,
output,
plugins: [
plugins: [
alias({
// 'vue': resolve('packages/uni-app-plus/dist/service.runtime.esm.js'),
'uni-core': resolve('src/core'),
'uni-platform': resolve('src/platforms/' + process.env.UNI_PLATFORM),
'uni-platforms': resolve('src/platforms'),
'uni-shared': resolve('src/shared/index.js'),
'uni-helpers': resolve('src/core/helpers'),
'uni-invoke-api': resolve('src/platforms/app-plus/service/api'),
'uni-service-api': resolve('src/core/service/platform-api'),
'uni-api-protocol': resolve('src/core/helpers/protocol')
}),
nodeResolve(),
commonjs(),
requireContext(),
alias({
'uni-core': resolve('src/core'),
'uni-platform': resolve('src/platforms/' + process.env.UNI_PLATFORM),
'uni-platforms': resolve('src/platforms'),
'uni-shared': resolve('src/shared/index.js'),
'uni-helpers': resolve('src/core/helpers'),
'uni-invoke-api': resolve('src/platforms/app-plus/service/api'),
'uni-service-api': resolve('src/core/service/platform-api'),
'uni-api-protocol': resolve('src/core/helpers/protocol')
}),
replace({
__GLOBAL__: 'getGlobalUni()',
__PLATFORM__: JSON.stringify('app-plus'),
__PLATFORM__: JSON.stringify(process.env.UNI_PLATFORM),
__PLATFORM_TITLE__: 'app-plus-nvue'
})
],
......
......@@ -12,6 +12,10 @@ if (process.env.UNI_PLATFORM === 'h5' && process.env.UNI_UI === 'true') {
outputDir = resolve('./packages/uni-' + process.env.UNI_PLATFORM + '-ui/dist')
}
if (process.env.UNI_PLATFORM === 'app-plus' && process.env.UNI_VIEW === 'true') {
outputDir = resolve('./packages/uni-' + process.env.UNI_PLATFORM + '/dist')
}
module.exports = {
publicPath: '/',
outputDir,
......
......@@ -5,54 +5,71 @@ const resolve = dir => path.resolve(__dirname, '../', dir)
const pkg = require('../package.json')
module.exports = {
mode: 'production',
devtool: false,
externals: {
vue: {
commonjs: 'vue',
commonjs2: 'vue',
root: 'Vue'
const externals = {}
if (process.env.UNI_VIEW !== 'true') {
externals['vue'] = {
commonjs: 'vue',
commonjs2: 'vue',
root: 'Vue'
}
externals['vue-router'] = {
commonjs: 'vue-router',
commonjs2: 'vue-router',
root: 'VueRouter'
}
}
const alias = {
'uni-core': resolve('src/core'),
'uni-view': resolve('src/core/view'),
'uni-service': resolve('src/core/service'),
'uni-shared': resolve('src/shared'),
'uni-mixins': resolve('src/core/view/mixins'),
'uni-helpers': resolve('src/core/helpers'),
'uni-platform': resolve('src/platforms/' + process.env.UNI_PLATFORM),
// tree shaking
'uni-components': resolve('src/core/view/components'),
'uni-invoke-api': resolve('src/platforms/' + process.env.UNI_PLATFORM + '/service/api'),
'uni-service-api': resolve('src/core/service/platform-api'),
'uni-api-protocol': resolve('src/core/helpers/protocol'),
'uni-api-subscribe': resolve('src/core/view/bridge/subscribe/api/index'),
// h5 components
'uni-h5-app-components': resolve('src/platforms/h5/components/app/popup/index'),
'uni-h5-app-mixins': resolve('src/platforms/h5/components/app/popup/mixins/index'),
'uni-h5-system-routes': resolve('src/platforms/h5/components/system-routes/index')
}
const provides = {
'console': [resolve('src/core/helpers/console'), 'default'],
'UniViewJSBridge': [resolve('src/core/view/bridge/index')],
'UniServiceJSBridge': [resolve('src/core/service/bridge/index')]
}
if (process.env.UNI_VIEW) { // 方便调试
delete provides['console']
}
module.exports = function configureWebpack (config) {
if (process.env.UNI_VIEW === 'true') {
delete config.externals['vue']
alias['vue$'] = resolve('packages/uni-app-plus/dist/view.runtime.esm.js')
}
return {
mode: 'production',
devtool: false,
externals,
resolve: {
alias
},
module: {
rules: []
},
'vue-router': {
commonjs: 'vue-router',
commonjs2: 'vue-router',
root: 'VueRouter'
}
},
resolve: {
alias: {
'uni-core': resolve('src/core'),
'uni-view': resolve('src/core/view'),
'uni-service': resolve('src/core/service'),
'uni-shared': resolve('src/shared'),
'uni-mixins': resolve('src/core/view/mixins'),
'uni-helpers': resolve('src/core/helpers'),
'uni-platform': resolve('src/platforms/' + process.env.UNI_PLATFORM),
// tree shaking
'uni-components': resolve('src/core/view/components'),
'uni-invoke-api': resolve('src/platforms/' + process.env.UNI_PLATFORM + '/service/api'),
'uni-service-api': resolve('src/core/service/platform-api'),
'uni-api-protocol': resolve('src/core/helpers/protocol'),
'uni-api-subscribe': resolve('src/core/view/bridge/subscribe/api/index'),
// h5 components
'uni-h5-app-components': resolve('src/platforms/h5/components/app/popup/index'),
'uni-h5-app-mixins': resolve('src/platforms/h5/components/app/popup/mixins/index'),
'uni-h5-system-routes': resolve('src/platforms/h5/components/system-routes/index')
}
},
module: {
rules: []
},
plugins: [
new webpack.DefinePlugin({
__VERSION__: JSON.stringify(pkg.version),
__PLATFORM__: JSON.stringify(process.env.UNI_PLATFORM)
}),
new webpack.ProvidePlugin({
'console': [resolve('src/core/helpers/console'), 'default'],
'UniViewJSBridge': [resolve('src/core/view/bridge/index')],
'UniServiceJSBridge': [resolve('src/core/service/bridge/index')]
})
]
plugins: [
new webpack.DefinePlugin({
__VERSION__: JSON.stringify(pkg.version),
__PLATFORM__: JSON.stringify(process.env.UNI_PLATFORM)
}),
new webpack.ProvidePlugin(provides)
]
}
}
export {
upx2px
}
from 'uni-core/service/api/base/upx2px'
export {
getSystemInfoSync
}
from '../../src/platforms/h5/service/api/device/get-system-info'
export function canIUse (schema) {
if (schema === 'css.var') {
return window.CSS && window.CSS.supports && window.CSS.supports('--a', 0)
}
return true
}
import Vue from 'vue'
import 'uni-core/view/index.css'
import {
definePage
} from 'uni-platform/view/framework/page'
import {
registerConfig
} from 'uni-platform/view/framework/config'
import ViewPlugin from 'uni-platform/view/framework/plugins/index'
global.UniViewJSBridge = {
publishHandler: UniViewJSBridge.publishHandler,
subscribeHandler: UniViewJSBridge.subscribeHandler
}
global.__registerConfig = registerConfig
global.__registerPage = definePage
global.Vue = Vue
Vue.use(ViewPlugin)
require('uni-components')
export * from './view-api.js'
......@@ -4,6 +4,7 @@
* 3.引入 Vue 组件
*/
import Vue from 'vue'
import initVue from 'uni-core/vue'
global.UniViewJSBridge = {
subscribeHandler: UniViewJSBridge.subscribeHandler
......@@ -34,6 +35,10 @@ Vue.use(require('uni-view/plugins').default, {
routes: __uniRoutes
})
require('uni-core/vue')
Vue.config.errorHandler = function (err, vm, info) {
UniServiceJSBridge.emit('onError', err)
}
initVue(Vue)
require('uni-platform/components')
require('uni-components')
{
"name": "uniapp-js-framework",
"version": "0.0.1",
"scripts": {
"scripts": {
"build:service:legacy": "npm run lint && rollup -c build/rollup.config.service.js",
"lint": "eslint --fix --config package.json --ext .js --ext .vue --ignore-path .eslintignore build src",
"lint:cli": "eslint --fix --config package.json --ignore-path .eslintignore packages/uni-cli-shared packages/uni-template-compiler \"packages/vue-cli-*/**/*.js\" \"packages/webpack-uni-*/**/*.js\"",
"dev:h5": "npm run lint && cross-env NODE_ENV=production UNI_WATCH=true UNI_PLATFORM=h5 node build/build.js",
"build:h5": "npm run lint && cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=h5 node build/build.js",
"build:h5": "npm run lint && cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=h5 node build/build.js",
"build:h5:ui": "cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=h5 UNI_UI=true node build/build.js",
"build:app-plus": "cross-env UNI_PLATFORM=app-plus rollup -c build/rollup.config.mp.js",
"build:app:all": "npm run lint && npm run build:app:nvue && npm run build:app:legacy",
"build:app:all": "npm run lint && npm run build:app:nvue && npm run build:app:legacy && npm run build:app:service && npm run build:app:view",
"build:app:v3": "npm run lint && npm run build:app:service && npm run dev:app:view",
"build:app:service": "cross-env UNI_PLATFORM=app-plus rollup -c build/rollup.config.app.js",
"build:app:view": "cross-env NODE_ENV=production UNI_WATCH=false UNI_PLATFORM=app-plus UNI_VIEW=true node build/build.js",
"dev:app:view": "cross-env NODE_ENV=production UNI_WATCH=true UNI_PLATFORM=app-plus UNI_VIEW=true node build/build.js",
"build:app:nvue": "cross-env UNI_PLATFORM=app-plus-nvue rollup -c build/rollup.config.app.js",
"build:app:legacy": "cross-env UNI_PLATFORM=app-plus-nvue UNI_SERVICE=legacy rollup -c build/rollup.config.app.js",
"build:mp-qq": "cross-env UNI_PLATFORM=mp-qq rollup -c build/rollup.config.mp.js",
......@@ -22,7 +26,7 @@
"test:cli": "cross-env NODE_ENV=test jest",
"test:unit": "cross-env NODE_ENV=test UNI_PLATFORM=h5 mocha-webpack --require tests/unit/setup.js --webpack-config build/webpack.config.test.js tests/unit/**/*.spec.js",
"release": "npm run lint:cli && lerna publish --force-publish=*",
"release:alpha": "npm run lint:cli && lerna publish --force-publish=* --npm-tag=alpha",
"release:alpha": "npm run lint:cli && lerna publish --force-publish=* --npm-tag=alpha",
"release:next": "npm run lint:cli && lerna publish --force-publish=* --npm-tag=next"
},
"dependencies": {
......@@ -126,4 +130,4 @@
"main": "index.js",
"description": "",
"author": ""
}
}
......@@ -1500,7 +1500,7 @@ var serviceContext = (function () {
});
}
function registerConfig (config) {
function registerConfig (config, Vue) {
Object.assign(__uniConfig, config);
__uniConfig.viewport = '';
......@@ -9156,7 +9156,11 @@ var serviceContext = (function () {
}
});
UniServiceJSBridge.publishHandler = UniServiceJSBridge.emit; // TODO
function publishHandler (event, args, pageId) {
// TODO
}
UniServiceJSBridge.publishHandler = publishHandler;
UniServiceJSBridge.invokeCallbackHandler = invokeCallbackHandler;
var index = {
......
<meta charset="utf-8">
<title>uni demo</title>
<script src="./view.umd.js"></script>
<link rel="stylesheet" href="./view.css">
<script>
console.log(uni)
</script>
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
因为 它太大了无法显示 source diff 。你可以改为 查看blob
......@@ -22,7 +22,8 @@ const {
} = require('./pages')
const {
md5,
md5,
hasOwn,
hasModule,
hashify,
camelize,
......@@ -63,7 +64,8 @@ const {
module.exports = {
md5,
tags,
tags,
hasOwn,
getJson,
parseJson,
hashify,
......
......@@ -202,7 +202,7 @@ function parsePages (pagesJson, pageCallback, subPageCallback) {
}
}
function parseEntry (pagesJson) {
function parseEntry (pagesJson) {
process.UNI_ENTRY = {
'common/main': path.resolve(process.env.UNI_INPUT_DIR, getMainEntry())
}
......
......@@ -27,6 +27,14 @@ function getShadowCss () {
}
function getCopyOption (file, options) {
if (path.isAbsolute(file)) {
if (fs.existsSync(file)) {
return Object.assign({
from: file,
to: path.resolve(process.env.UNI_OUTPUT_DIR)
}, options)
}
}
const from = path.resolve(process.env.UNI_INPUT_DIR, file)
if (fs.existsSync(from)) {
return Object.assign({
......@@ -125,12 +133,17 @@ const PLATFORMS = {
}) {
const files = ['hybrid/html']
let wxcomponents = []
if (!process.env.UNI_USING_NATIVE) {
if (!process.env.UNI_USING_NATIVE && !process.env.UNI_USING_V3) {
wxcomponents = getCopyOptions(['wxcomponents'], {
to: path.resolve(process.env.UNI_OUTPUT_TMP_DIR, 'wxcomponents')
})
}
let template = []
if (process.env.UNI_USING_V3) {
template = getCopyOptions([path.resolve(__dirname, '../template')])
}
return [
...template,
...getStaticCopyOptions(assetsDir),
...wxcomponents,
...getCopyOptions(files)
......@@ -484,6 +497,9 @@ module.exports = {
if (process.env.UNI_PLATFORM === 'h5' && vueOptions && vueOptions.runtimeCompiler) {
return '@dcloudio/vue-cli-plugin-uni/packages/h5-vue/dist/vue.esm.js'
}
if (process.env.UNI_PLATFORM === 'app-plus' && process.env.UNI_USING_V3) {
return '@dcloudio/uni-app-plus/dist/service.runtime.esm.js'
}
if (process.env.UNI_USING_COMPONENTS) {
return uniRuntime
}
......
此差异已折叠。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<style>
html,
body,
.container {
margin: 0;
padding: 0;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: #ffffff;
}
#map {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 80px;
bottom: calc(80px + constant(safe-area-inset-bottom));
bottom: calc(80px + env(safe-area-inset-bottom));
}
#poi {
position: absolute;
left: 0;
right: 0;
bottom: 0;
bottom: constant(safe-area-inset-bottom);
bottom: env(safe-area-inset-bottom);
height: 80px;
background: #FFFFFF;
}
.poi-info {
width: 100%;
padding: 23px 16px 23px 18px;
box-sizing: border-box;
background: #FFFFFF;
}
.poi-name {
font-size: 17px;
line-height: 17px;
color: #111111;
display: block;
margin-right: 70px;
word-wrap: break-word;
}
.poi-addr {
font-size: 13px;
line-height: 13px;
color: #666666;
display: block;
margin-top: 4px;
margin-right: 70px;
word-wrap: break-word;
}
.poi-nav {
display: block;
position: absolute;
top: 10px;
right: 16px;
width: 60px;
height: 60px;
border-radius: 60px;
overflow: hidden;
}
.poi-nav i,
.poi-nav span {
position: absolute;
top: 0;
width: 100%;
height: 100%;
display: inline-block;
border-radius: 60px;
}
.poi-nav i {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHgAAAB4CAMAAAAOusbgAAACnVBMVEUAAAA9avA+avA9avA/bPE8afA+avM9afA9avA9au9Ac/I+bPQ9avA8a/E8au8+avY9avA9avBAgP88avA9au9AbfFAgP89avA9avBJbf89au88afA8ae88afA8ae9AbO88afA/avE9ae88avBHcfFCcfY+a/H///89afE8afA8avA9afA8afA9a/E9afA9avA8avA8avA9ae////88ae8/a+/+/v77/P5Cbu9jh/I9au9Te/CIo/XY4fuasfbH1PpJc/Dl6/xHce9Cbe9Eb+9FcO/3+f5SevC0xfjh6PygtvdLdPD4+f7e5fytwPj9/f7y9f1agPG6yvlsjvNIcvC8y/lXfvFNdvBZf/HR3PtBbe+DoPTT3fvg5/xWffGyxPh/nPTo7f32+P65yfnBz/n6+/6xw/i+zfmwwvj5+v6Np/WetPdPd/BMdfBOd/BdgvGkufdGce9ghfKnu/deg/F4l/NqjPKAnfS3x/lAbO+KpfVPePBmifKqvviZsPait/fS3PtUe/F6mfT8/f7s8P2Xr/bX4PuWrvbI1fqdtPfq7/3t8f3E0vqCn/RRefCzxPjK1vpwkfPP2vtVfPHR2/tDbu+BnvTr8P3G0/qLpvXW3/uOqPXL1/rf5vyht/eDn/Rzk/OPqfWQqfXZ4vuGovX19/67y/nm7Pymuvc+au9hhfKluvfU3vt3lvO3yPlpjPJykvN2lfNQePB7mfSsv/ju8v18mvTO2fvv8/22x/nr7/2cs/aMpvXn7P3D0fp+nPR5mPTE0frj6fyftfdcgfFfhPHN2Prx9P1ihvJ2lvO/zvm9zPl0lPOHo/VsjvKovPeQqvX09v6TrPZ1lfOUrfZnivKVrfbM2PrAzvmuwfi1xvjC0Pri6fzz9v59m/T8d63OAAAAM3RSTlMA7GNUSf4p38bFFC3nN7Id75oI/eI4BIv7B9Kl9fnCQLs1ossSG2sBS/p7rJlYuLmYrcSkuUTkAAAGJElEQVR4XsWbVXvbShBAJbumJE0abp0mbdI23KS9M4YgM0ORmZmZmZkZLjMzMzPDb7m2NvJnx8p6pVjd86J18nA+raSFmVlBNXGRxtyMApvdIqamiha7rSAj1xgZJ+iLOTPPEo8KxFvyMs06SSMMKVFIJSrFEBFu6zBjdA4ykBNtHBZGbfq4IcjMkHHpYdKOGIkqGTkiDNpBNtSAbdAAtYNHoUZGDRa0MzrWhJoxxY7WqM0yiDggREOWFm9MGg6YtBj13mwRw4CYrVKblGzCsGBKTlLjHWPFsGEdw+41J2AYSWCePRJFDCtiIuNYNRzDzHCmcWzsUAw7Q8cy3C/xhtsc8p4T1fbz7TUXmXo7xHM2i6iSb2Hus8iAaKZ+vwmoXgzwYQnLV0X5npOsqEkM9QcdGBJr/2NYMmoUA9zswZAk9zsvmLSJCc+txBCYspW9MSIORAyd7xQjHVFxlsxKQ+1iwrUipJOmtDIw4IDF0PFKNVIxKKyvWDu68vbEQ2+5OnxAAAc2Iw0xeB0Wi0zsnb8f6NyYghRig9axJmSguHkhhGRh8zTKm9131cu0fq6uAAY6tyGFUX3mJGTAXQYMvLkSqQTOUzZk4GsGbdsmDMEjAfsyZGAbEFrbz253FMuUgh/zDjOM2f47Opb9YO1xIqjY3u93vKABGRgp+EhHBnYRQWMx9iN+/EVkI90nzkcG2iTBMw5UFi+85UZG8mXvMJb9/iQi2IHK4s+6kJkhcrTCyD4mlyn//fglVINRIEQjA29L4t1K4o72CaiKaOKNyEEGlkjibQriQ0WokpwIFfNhtyQOnnteXkaZ/umzY4pWsXZSJHHUwxdHeb1mfPhiNHvEmTzEmR7xeB7iPI/YwkNsEYS4eB7i+DghEnmIMVIw8hEbhVw+4lwhg484QyjkIy4UrHzEVsHOR2wXLHzEFkHkIxaFVD7iVG5i5q4u2ujlpfB1tQW5YBHsyAW7YEMu2IQC5EKBkIFcyBBykQu5ghG5YGRZ+qzasmUV+uFYhzJfrrmKmohkWexNAfAPmk17b+kHcns9fIQ+znf2ZSVlsSdY1IonnIP9pUjY4f+vWdCXyZTlrZBHCeQRugC6epuSYOt8gIO4eo6Hza2waI6XvUTcs8FDBVR4L99QxHnULcwmCOIplGiEN1YsB3+mS2Ji6oZulH9StjBmDeInZ3+K12fKuODyzI3E9HyXhytwxXt5gSI2U7epdUWEfQD7eptuDKbLCatVPuMosjFnerkUOLq8mAQp2lAWz3vUgwtc3ku9JKZszA0qxa894WEZ4kaAI5WILa1QTsTsz9ggB19UiWeDh6mIeM8F7xZhObhKVIpzIqjhpi0ze6kCqJLbpxHn7Nx5RhJjz6uwdNkBaEefuPyehzIo814+7lccTQ+wvQ4KnJEU04kYG8oAoH6V2gHESA8p/lwq0Q7QXOrjToAY3XsA7tcgYfJjhLkwt7dVTQ8p0oOoe4jk7NNICBAf7gCAG7XoQ37GNMYxhY3fJ4HTdU54ECSumQ8w9SjADHJnjl4mwkS5SQsb0wPllcdgsdRYBPWfBIpr71YBLK7BcoD7LYhYAsGUUALl9NTAYmidJDUuNkGb21+863MAkPq/GeDmCnbxCJZkyF3w9fAXLliChOLZ0LT1N3B+tU6elafWITom9XICTshNhb62saR/TjrhNBIcpxrB+R1pLgCAc5O/X40yP9Sxv1yDQie8HGuc8OPVn3YvWnChqRO8NEk5tFuwtLwKqn75taFyba17Wk1ddcupLqy8RyADiMxa5YQXPcW3AvyY9/i1iv2wHBF7OuABVl6AAI7hFFDifFCKjyWpeeT3PxrXl18/eaeoQXqv/oS/EHHD5QrvlHzp73/+dYJMN5bMUGI7JanJnsZt+Y8MjbNQZqu7du0ELzXIhDiakrjWEwMlVa8naVmU4gQdEWMo5Rg6YsqmFKDoSTKt5EZHrEnUIiPdSBjDUFalA6KZoZBMB4Yn8iqd41UsyKs8kldBKK8SWF5Fv7zKnHkVdvMvZedfvM//uAL/Axr8j6TwP4RDSM9Xc+woP53TQStOR8v0wZw5XvfDdPTjg4VW+figtVDb8cH/AZ+Eg+9jqX0NAAAAAElFTkSuQmCC) no-repeat;
background-size: 100%;
}
</style>
</head>
<body>
<div id="container" class="container">
<div id="map"></div>
<div id="poi">
<div class="poi-info">
<span class="poi-name"></span>
<span class="poi-addr"></span>
<div class="poi-nav">
<i></i>
<span></span>
</div>
</div>
</div>
</div>
<script>
var loc;
var serviceWebview;
var back = function() {
var webview = plus.webview.currentWebview()
if (webview.__uniapp_statusbar_style === 'light') {
plus.navigator.setStatusBarStyle('light')
}
webview.close('auto');
};
var isIos = !!navigator.userAgent.match(/iPhone|iPad|iPod/i);
document.addEventListener('plusready', function() {
serviceWebview = plus.webview.getWebviewById('__W2A_CONTEXT_') || plus.webview.getLaunchWebview();
plus.key.addEventListener('backbutton', back);
})
/**
* 调用系统第三方程序进行导航
*/
function openSysMap(lat, lng, title) {
/**
* 网页版地图源
*/
var mapsSourceWeb = [
{
title: '腾讯地图网页版',
getUrl: function() {
var url
url = 'https://apis.map.qq.com/uri/v1/routeplan?type=drive' + '&to=' +
encodeURIComponent(title) + '&tocoord=' + encodeURIComponent(lat + ',' + lng) +
'&referer=APP'
return url
}
}
]
/**
* APP版地图源
*/
var mapsSource = [
{
title: '高德地图',
pname: 'com.autonavi.minimap',
action: !isIos ? 'amapuri://' : 'iosamap://',
getUrl: function() {
var url
if (!isIos) {
url = 'amapuri://route/plan/'
} else {
url = 'iosamap://path'
}
url += '?sourceApplication=APP&dname=' + encodeURIComponent(title) + '&dlat=' + lat +
'&dlon=' + lng + '&dev=0'
return url
}
},
{
title: '百度地图',
pname: 'com.baidu.BaiduMap',
action: 'baidumap://',
getUrl: function() {
var url = 'baidumap://map/direction?destination=' + encodeURIComponent('latlng:' + lat +
',' + lng + '|name:' + title) + '&mode=driving&src=APP&coord_type=gcj02'
return url
}
},
{
title: '腾讯地图',
pname: 'com.tencent.map',
action: 'qqmap://',
getUrl: function() {
var url
url = 'qqmap://map/routeplan?type=drive' + (isIos ? ('&from=' + encodeURIComponent(
'我的位置')) : '') + '&to=' + encodeURIComponent(title) + '&tocoord=' +
encodeURIComponent(lat + ',' + lng) + '&referer=APP'
return url
}
}
]
var maps = []
mapsSource.forEach(function(mapsSource) {
var installed = plus.runtime.isApplicationExist({
pname: mapsSource.pname,
action: mapsSource.action,
})
if (installed) {
maps.push(mapsSource)
}
})
if (isIos) {
maps.unshift({
title: 'Apple 地图',
getUrl: function() {
var url
url = 'https://maps.apple.com/?daddr=' + encodeURIComponent(title) + '&sll=' +
encodeURIComponent(lat + ',' + lng)
return url
}
})
}
if (maps.length === 0) {
maps = maps.concat(mapsSourceWeb)
}
plus.nativeUI.actionSheet({
title: '导航方式',
cancel: '取消',
buttons: maps,
}, function(res) {
var index = res.index
var map
if (index > 0) {
map = maps[index - 1]
plus.runtime.openURL(map.getUrl(), function() { }, map.pname)
}
})
}
var ZOOM = 13
window.__openLocation__ = function(params) {
var mapElem = document.getElementById('map');
var poiNameElem = document.querySelector('.poi-name');
var poiAddrElem = document.querySelector('.poi-addr');
var poiNavElem = document.querySelector('.poi-nav');
var latitude = params.latitude;
var longitude = params.longitude;
var scale = params.scale;
var name = params.name;
var address = params.address;
var point = new plus.maps.Point(longitude, latitude);
var map = plus.maps.create('map', {
center: point,
zoom: scale || ZOOM,
top: 0,
left: 0,
width: mapElem.offsetWidth,
height: mapElem.offsetHeight
});
var marker = new plus.maps.Marker(point);
marker.setIcon('__uniappmarker@3x.png');
if (name) {
poiNameElem.innerText = name;
// marker.setLabel(name);
}
if (address) {
poiAddrElem.innerText = address;
// var bubble = new plus.maps.Bubble(address);
// marker.setBubble(bubble);
}
map.addOverlay(marker);
plus.webview.currentWebview().append(map);
var userPoint = false
map.getUserLocation(function(state, point) {
if (state) {
plus.nativeUI.toast('定位失败!');
} else {
userPoint = point;
}
})
poiNavElem.addEventListener('click', function() {
openSysMap(latitude, longitude, name)
});
}
</script>
</body>
</html>
\ No newline at end of file
此差异已折叠。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports(
'top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title>扫码</title>
<style>
html,
body,
.container {
margin: 0;
padding: 0;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: #000000;
}
</style>
</head>
<body>
<div id="scan" class="container">
</div>
<script>
var scan;
var lightImg;
var lightView;
var back = function(cancel) {
if (cancel) {
plus.webview.postMessageToUniNView({
type: 'scanCode',
args: {
errMsg: 'cancel'
}
}, '__uniapp__service');
}
lightImg && lightImg.clear();
lightView && lightView.clear();
scan && scan.close();
var webview = plus.webview.currentWebview();
if (webview.__uniapp_dark) {
plus.navigator.setStatusBarStyle('dark');
}
webview.close('auto');
}
/**
* 绘制照亮开关
*/
function drawLight() {
var offImg =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABjklEQVRoQ+1ZbVHEQAx9TwE4ABTcOQAknANQAKcAUAAOAAXgAHAACsDCKQiTmbYDzJZtNt2bFrJ/m6+Xl2yyU2LmhzOPH/8PgIjcADirxNyapNoffMwMiMgzgMPBHmyCLySPLCoBwJKtAbJbYaBmD1yRvBwAtBMxl5DF+DZkiwCIyBLAzsgBbki+Wm2WAlCaL6zOMvKnJO+sNksB7ALQbO1ZHfbIv5FUVs2nCIB6EZETALdmj2mFY5I6X8ynGEADQllYmL1+VzBfnV/VvQB0aj45ARyQ/Ci14QLQsOBZLe5JaikWnzEA7AN4L4hgA2Dpyb76dANwsOCq/TZhASAYKGie0a7R1lDPI0ebtF0NUi+4yfdAtxr3PEMnD6BbD0QkNfACQO05EAwMuaBqDrIVycdmTpwDuP4R0OR7QFftVRP0g+49cwOQq4DJMxAAchmofY3m/EcJBQOZbTRKKJeBKKEoIePvpFRJ1VzmciUccyCa+C81cerBkuuB7sGTE/zt+yhN7AnAqxsAvBn06n8CkyPwMZKwm+UAAAAASUVORK5CYII=';
var onImg =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAB4klEQVRoQ+1ZQU7CUBCdaWVBLFETqUtxB7iQG4hH4AZ4AvUE4gnkBuoJ9AbiDXAhZadby4IQICaS9psqJBVLy5/fkhKHbefPzPvzZv6bgLDmP1zz/OH/ARjZpSYAniVSORQXRt5qyviWrsDQLrUQ8FgmyLK2AsRTzrSqy9p7dgxA5raibFdSgSR7QAi4yu11GlFA/d+lKSTjfBW2JAAj+7Cio7MVZ4KO0AeG+dKW9UkCMHwvNxDhUjZYuL17apjdW1mfJACiX9gef2bbgLgvG3CB/bNhdioUXyQAXqCRXawDaDeUoPNnBLonuXy3RfFFBvADouxx9ogSeHaGMjpjm0LDXrGKQntUAaBn3IPsTveN6kOpAl5QNWkh7gzTqlOTJ0mJ+WAf/WLBmWivskkIEIONjKio3H4sAKhVUOX+7MKUKcQAZLk3Z88VWEQhr0kRYCoN/m5wqe8BvzQOkuDpB+CTB0EPHgOYNnNiTewXaFyBkFGbWAVQE7XNXevhW7X2Sucg8NqfR+p7AADaesateUk7E+0eAH4tLOsAIPSNZQBJT6EoicMV4Ar4OEJZK5lCTCGmkPy/MUGjOTEtxO9A1A1wE3MTp6iJgxaWKAr7F54o27DvsUwhlQRUzzIA1RtUPf8FRKRYQOI+9hQAAAAASUVORK5CYII=';
var onText = '轻触照亮';
var offText = '轻触关闭';
var on = false;
var viewWidth = 48;
var fontSize = 12;
var imgWidth = 30;
function changeType() {
lightView.reset();
lightImg.loadBase64Data(on ? onImg : offImg, function() {
lightView.drawBitmap(lightImg, {}, {
top: 0,
left: (viewWidth - imgWidth) / 2 + 'px',
width: imgWidth + 'px',
height: imgWidth + 'px'
});
});
lightView.drawText(on ? offText : onText, {
top: imgWidth + 'px',
left: '0px',
width: '100%',
height: fontSize + 'px'
}, {
color: '#ffffff',
size: fontSize + 'px'
});
scan.setFlash(on);
on = !on;
}
lightImg = new plus.nativeObj.Bitmap('lightImg');
lightView = new plus.nativeObj.View('lightView', {
width: viewWidth + 'px',
height: viewWidth + 'px',
top: window.innerHeight / 2 + 50 + 'px',
left: (window.innerWidth - viewWidth) / 2 + 'px',
position: 'static'
});
lightView.addEventListener('click', function() {
changeType();
});
plus.webview.currentWebview().append(lightView);
changeType();
}
document.addEventListener('plusready', function() {
var serviceWebview = plus.webview.getWebviewById('__W2A_CONTEXT_') || plus.webview.getLaunchWebview();
plus.key.addEventListener('backbutton', function() {
back(true);
});
setTimeout(function() {
var webview = plus.webview.currentWebview();
scan = new plus.barcode.Barcode('scan', webview.__uniapp_scan_type, {
frameColor: '#118CE9',
scanbarColor: '#118CE9'
});
scan.onmarked = function(type, code, file) {
var res = {
type: type,
code: code
};
back()
plus.webview.postMessageToUniNView({
type: 'scanCode',
args: res
}, '__uniapp__service');
};
scan.onerror = function(error) {
back()
plus.webview.postMessageToUniNView({
type: 'scanCode',
args: {
errMsg: error.message + ',错误码:' + error.code
}
}, '__uniapp__service');
};
scan.start();
drawLight();
}, 500)
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<script>
var __UniViewStartTime__ = Date.now();
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title>View</title>
<style>
* {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-tap-highlight-color: transparent;
}
input[type="search"i]::-webkit-search-cancel-button {
display: none;
}
</style>
<link rel="stylesheet" href="view.css" />
<script>
/*CONFIG*/
</script>
<script>
var __id__ = '';
window.__dispatchGenerateFunc__ = function(page) {
__id__ = page;
document.title = page;
// window.history.pushState('', '', page);
var wxss = page.replace('.html', '.wxss')
if (
typeof __wxAppCode__ !== 'undefined' &&
__wxAppCode__.hasOwnProperty(wxss)
) {
var setCssToHead = __wxAppCode__[wxss]
typeof setCssToHead === 'function' && setCssToHead()
document.dispatchEvent(new CustomEvent("generateFuncReady", {
detail: {
generateFunc: $gwx(page.replace('.html', '.wxml'))
}
}));
} else {
plus.webview.currentWebview().setJsFile('_www/' + page.replace('.html', '.js'));
}
};
</script>
<script src="__uniappes6.js"></script>
<script src="view.umd.js"></script>
<script src="app-view.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
此差异已折叠。
此差异已折叠。
......@@ -643,14 +643,6 @@
"/platforms/h5/service/api/ui/window.js",
[]
],
"startPullDownRefresh": [
"/platforms/h5/service/api/ui/pull-down-refresh.js",
[]
],
"stopPullDownRefresh": [
"/platforms/h5/service/api/ui/pull-down-refresh.js",
[]
],
"createSelectorQuery": [
"/platforms/h5/service/api/ui/create-selector-query.js",
[
......
const compiler = require('../lib')
function assertCodegen (template, generatedCode, ...args) {
const compiled = compiler.compile(template, {
mp: {
platform: 'app-plus'
},
service: true
})
expect(compiled.render).toBe(generatedCode)
}
/* eslint-disable quotes */
describe('codegen', () => {
it('generate directive', () => {
assertCodegen(
'<p v-custom1:[arg1].modifier="value1" v-custom2></p>',
`with(this){return _c('p',{extras:{"v-custom1":value1,"v-custom1-arg":arg1},attrs:{"_i":0}})}`
)
})
it('generate v-for directive', () => {
assertCodegen(
'<div><template v-for="item in items"><div></div><div></div></template></div>',
`with(this){return _c('div',{attrs:{"_i":0}},[_l((items),function(item,$i){return [_c('div',{key:_$f(1,{forIndex:$i,keyIndex:0,key:'1-0-'+$i}),attrs:{"_i":("2-"+$i)}}),_c('div',{key:_$f(1,{forIndex:$i,keyIndex:1,key:'1-1-'+$i}),attrs:{"_i":("3-"+$i)}})]})],2)}`
)
assertCodegen(
'<div><template v-for="item in items">text</template></div>',
`with(this){return _c('div',{attrs:{"_i":0}},[_l((items),function(item,$i){return [_c('text',{key:_$f(1,{forIndex:$i,keyIndex:0,key:'1-0-'+$i}),attrs:{"_i":("1-"+$i)}})]})],2)}`
)
assertCodegen(
'<div><template v-for="item in items">{{text}}</template></div>',
`with(this){return _c('div',{attrs:{"_i":0}},[_l((items),function(item,$i){return [_c('text',{key:_$f(1,{forIndex:$i,keyIndex:0,key:'1-0-'+$i}),extras:{t0:_s(text)},attrs:{"_i":("1-"+$i)}})]})],2)}`
)
assertCodegen(
'<div><template v-for="item in items"><span></span>{{text}}</template></div>',
`with(this){return _c('div',{attrs:{"_i":0}},[_l((items),function(item,$i){return [_c('span',{key:_$f(1,{forIndex:$i,keyIndex:0,key:'1-0-'+$i}),attrs:{"_i":("2-"+$i)}}),_c('text',{extras:{t0:_s(text)},attrs:{"_i":("1-"+$i)}})]})],2)}`
)
assertCodegen(
'<div><template v-for="item in items">a {{text1}} b {{text2}}</template></div>',
`with(this){return _c('div',{attrs:{"_i":0}},[_l((items),function(item,$i){return [_c('text',{key:_$f(1,{forIndex:$i,keyIndex:0,key:'1-0-'+$i}),extras:{t0:_s(text1),t1:_s(text2)},attrs:{"_i":("1-"+$i)}})]})],2)}`
)
})
it('generate text with multiple statements', () => {
assertCodegen(
'<div>A{{ d | e | f }}B{{text}}C</div>',
`with(this){return _c('div',{attrs:{"_i":0}},[_c('text',{extras:{t0:_s(_f("f")(_f("e")(d))),t1:_s(text)},attrs:{"_i":0}})])}`
)
})
})
/* eslint-enable quotes */
const compiler = require('../lib')
function assertCodegen (template, generatedCode, ...args) {
const compiled = compiler.compile(template, {
mp: {
platform: 'app-plus'
},
view: true
})
expect(compiled.render).toBe(generatedCode)
}
/* eslint-disable quotes */
describe('codegen', () => {
it('generate directive', () => {
assertCodegen(
'<p v-custom1:[arg1].modifier="value1" v-custom2></p>',
`with(this){return _c('p',{directives:[{name:"custom1",rawName:"v-custom1:[arg1].modifier",value:($r['0']['v-custom1']),expression:"$r['0']['v-custom1']",arg:$r['0']['v-custom1-arg'],modifiers:{"modifier":true}},{name:"custom2",rawName:"v-custom2"}],attrs:{"_i":0}})}`
)
})
it('generate v-for directive', () => {
assertCodegen(
'<div><template v-for="item in items"><div></div><div></div></template></div>',
`with(this){return _c('div',{attrs:{"_i":0}},[_l(($r['1']['v-for']),function(item,$i){return [_c('div',{key:item['k0'],attrs:{"_i":("2-"+$i)}}),_c('div',{key:item['k1'],attrs:{"_i":("3-"+$i)}})]})],2)}`
)
})
it('generate events with multiple statements', () => {
assertCodegen(
'<div>A{{ d | e | f }}B{{text}}C</div>',
`with(this){return _c('div',{attrs:{"_i":0}},[_v("A"+($r['0']['t-0'])+"B"+($r['0']['t-1'])+"C")])}`
)
})
})
/* eslint-enable quotes */
const compiler = require('../lib')
const res = compiler.compile(
`
<button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">获取手机号</button>
<view>
<component v-for="component in components" :item="component.item" :is="component.mode"/>
</view>
`, {
resourcePath: '/User/fxy/Documents/test.wxml',
mp: {
minified: true,
isTest: true,
platform: 'mp-weixin'
platform: 'app-plus'
},
filterModules: {
t: {},
a: {}
}
// service: true
view: true
})
// ---BEGIN:JSON---{"n":"v"}---END:JSON---
console.log(res)
console.log(require('util').inspect(res, {
colors: true,
depth: null
}))
/* @flow */
const validDivisionCharRE = /[\w).+\-_$\]]/
module.exports = function parseFilters (exp) {
let inSingle = false
let inDouble = false
let inTemplateString = false
let inRegex = false
let curly = 0
let square = 0
let paren = 0
let lastFilterIndex = 0
let 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) { // /
let j = i - 1
let p
// 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) {
const i = filter.indexOf('(')
if (i < 0) {
// _f: resolveFilter
return `_f("${filter}")(${exp})`
} else {
const name = filter.slice(0, i)
const args = filter.slice(i + 1)
return `_f("${name}")(${exp}${args !== ')' ? ',' + args : args}`
}
}
const {
tags,
hasOwn
} = require('@dcloudio/uni-cli-shared')
const {
ID,
addAttr
} = require('./util')
module.exports = function preTransformNode (el, options) {
if (el.tag.indexOf('v-uni-') !== 0 && hasOwn(tags, el.tag)) {
el.tag = 'v-uni-' + el.tag
}
if (!hasOwn(options, 'nid')) {
options.nid = 0
}
addAttr(el, ID, options.nid++)
if (el.attrsMap['v-for']) {
el.forId = el.attrsMap[ID]
}
}
const {
ID,
ITERATOR,
isVar,
getForEl,
processForKey,
updateForEleId
} = require('./util')
const parseText = require('./text-parser')
const preTransformNode = require('./pre-transform-node')
function genData (el) {
const {
events,
dynamicClass,
dynamicStyle,
dynamicAttrs,
dynamicTexts,
directivesBinding
} = el
let extras = ''
if (directivesBinding) {
const dirs = genDirectives(directivesBinding)
dirs && (extras += dirs + ',')
}
if (dynamicClass) {
extras += genDynamicClass(dynamicClass) + ','
}
if (dynamicStyle) {
extras += genDynamicStyle(dynamicStyle) + ','
}
if (dynamicTexts) {
extras += genDynamicTexts(dynamicTexts) + ','
}
if (events) {
const dynamicHandlers = genDynamicHandlers(events)
dynamicHandlers && (extras += dynamicHandlers + ',')
}
if (Array.isArray(dynamicAttrs)) {
const dynamicProps = genDynamicProps(dynamicAttrs)
dynamicProps && (extras += dynamicProps + ',')
}
extras = extras.replace(/,$/, '')
if (extras) {
return `extras:{${extras}},`
}
return ''
}
function genDirectives (dirs) {
let directives = []
dirs.forEach(dir => {
isVar(dir.value) && directives.push(`"v-${dir.name}":${dir.value}`)
dir.isDynamicArg && (directives.push(`"v-${dir.name}-arg":${dir.arg}`))
})
return directives.join(',')
}
function genDynamicClass (classBinding) {
return `c:${classBinding}`
}
function genDynamicStyle (styleBinding) {
return `s:${styleBinding}`
}
function genDynamicTexts (dynamicTexts) {
return dynamicTexts.map(({
name,
value
}) => {
return `${name}:${value}`
}).join(',')
}
function genDynamicHandlers (events) {
let dynamicHandlers = []
let index = 0
for (let name in events) {
const eventHandler = events[name]
if (eventHandler.dynamic) {
eventHandler.index = index++
dynamicHandlers.push('"de-' + (eventHandler.index) + '":' + name)
}
}
return dynamicHandlers.join(',')
}
function genDynamicProps (props, prefix = 'da') {
let dynamicProps = []
let index = 0
for (let i = 0; i < props.length; i++) {
const {
name,
value,
dynamic
} = props[i]
if (dynamic) {
props[i].index = index++
dynamicProps.push(`"${prefix}-` + (props[i].index) + '-n":' + name)
dynamicProps.push(`"${prefix}-` + (props[i].index) + '-v":' + value)
}
}
return dynamicProps.join(',')
}
// if 使用该方案是因为 template 节点之类无法挂靠 extras
function processIfConditions (el) {
if (el.if) {
el.ifConditions.forEach(con => {
if (isVar(con.exp)) {
const method = con.block.elseif ? '_$e' : '_$i'
con.exp = `${method}(${con.block.attrsMap[ID]},${con.exp})`
}
})
el.if = `_$i(${el.attrsMap[ID]},${el.if})`
}
el.children && el.children.forEach(child => {
processIfConditions(child)
})
el.scopedSlots && Object.values(el.scopedSlots).forEach(child => {
processIfConditions(child)
})
}
function removeStatic (el) {
delete el.staticClass
delete el.staticStyle
}
function renameBinding (el) {
// 重命名 classBinding,styleBinding,避免生成 class,style 属性
if (el.classBinding) {
el.dynamicClass = el.classBinding
delete el.classBinding
}
if (el.styleBinding) {
el.dynamicStyle = el.styleBinding
delete el.styleBinding
}
}
function processKey (el) {
// add default key
if (processForKey(el)) {
el = el.children[0] // 当 template 下仅文本时,处理第一个动态文本
}
if (el.key) { // renderList key
const forEl = getForEl(el)
if (forEl) {
if (!isVar(forEl.for)) {
return
}
const forId = forEl.forId
const it = forEl.iterator2 || forEl.iterator1 || ITERATOR
if (forEl === el) { // <view v-for="item in items" :key="item.id"></view>
el.key = `_$f(${forId},{forIndex:${it},key:${el.key}})`
} else { // <template v-for="item in items"><view :key="item.id+'1'"></view><view :key="item.id+'2'"></view></template>
const keyIndex = forEl.children.indexOf(el)
el.key = `_$f(${forId},{forIndex:${it},keyIndex:${keyIndex},key:${el.key}})`
}
} else {
isVar(el.key) && (el.key = `_$s(${el.attrsMap[ID]},'a-key',${el.key})`)
}
}
}
function processIf (el) {
// 因为时机问题,在最后处理根节点时,遍历处理 ifConditions
!el.parent && processIfConditions(el)
}
function processDirs (el) {
if (el.directives) {
const directivesBinding = []
el.directives = el.directives.filter(dir => {
directivesBinding.push(dir)
if (dir.name === 'model') {
return true
}
})
if (directivesBinding.length) {
el.directivesBinding = directivesBinding
}
if (!el.directives.length) {
delete el.directives
}
}
}
function processDynamicText (el, state) {
el.type = 1
el.tag = 'text'
el.attrsList = [{
name: ID,
value: state.id
}]
el.attrsMap = {
[ID]: state.id
}
el.rawAttrsMap = {}
el.children = []
el.plain = false
el.attrs = [{
name: ID,
value: String(state.id)
}]
el.hasBindings = true
if (el.text) {
const ret = parseText(el.text, false, state)
if (ret && ret.dynamicTexts.length) {
el.dynamicTexts = ret.dynamicTexts
}
}
delete el.expression
delete el.tokens
delete el.text
return el
}
function processText (el) {
if (!el.children.length) {
return
}
const state = {
id: el.attrsMap[ID],
index: 0,
service: true
}
el.children = el.children.filter(child => {
if (child.type === 3) { // ASTText
return false
} else if (child.type === 2 && child.text) { // ASTExpression
processDynamicText(child, state)
child.parent = el
}
return true
})
// <div><template v-for="item in items">item</template></div>
if (!el.children.length && el.tag === 'template' && el.for) {
el.children.push(processDynamicText({
parent: el
}, state))
}
}
function postTransformNode (el) {
removeStatic(el)
renameBinding(el)
processText(el)
updateForEleId(el)
processKey(el)
processIf(el)
processDirs(el)
}
module.exports = {
preTransformNode,
postTransformNode,
genData
}
/* @flow */
const parseFilters = require('./filter-parser')
function cached (fn) {
const cache = Object.create(null)
return function cachedFn (str) {
const hit = cache[str]
return hit || (cache[str] = fn(str))
}
}
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g
const regexEscapeRE = /[-.*+?^${}()|[\]/\\]/g
const buildRegex = cached(delimiters => {
const open = delimiters[0].replace(regexEscapeRE, '\\$&')
const close = delimiters[1].replace(regexEscapeRE, '\\$&')
return new RegExp(open + '((?:.|\\n)+?)' + close, 'g')
})
module.exports = function parseText (
text,
delimiters,
state
) {
const tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE
if (!tagRE.test(text)) {
return
}
const dynamicTexts = [] // fixed by xxxxxx
const tokens = []
const rawTokens = []
let lastIndex = tagRE.lastIndex = 0
let match, index, tokenValue
while ((match = tagRE.exec(text))) {
index = match.index
// push text token
if (index > lastIndex) {
rawTokens.push(tokenValue = text.slice(lastIndex, index))
if (!state.service) {
tokens.push(JSON.stringify(tokenValue))
}
}
// tag token
const exp = parseFilters(match[1].trim())
if (state.service) {
dynamicTexts.push({
name: `t${state.index++}`,
value: `_s(${exp})`
})
} else {
tokens.push(`(${state.genVar('t' + (state.index++))})`)
}
rawTokens.push({
'@binding': exp
})
lastIndex = index + match[0].length
}
if (lastIndex < text.length) {
rawTokens.push(tokenValue = text.slice(lastIndex))
if (!state.service) {
tokens.push(JSON.stringify(tokenValue))
}
}
return {
expression: tokens.join('+'),
tokens: rawTokens,
dynamicTexts
}
}
const VARS = ['true', 'false', 'null']
const NUMBER_RE = /^-?\d*(\.\d+)?$/
const ID = '_i'
const ITERATOR = '$i'
const DATA_ROOT = '$r'
function isVar (str) {
if (!str) {
return false
}
const firstLetter = str[0]
if (
firstLetter === '"' || // string
firstLetter === '\'' || // string
VARS.includes(str) || // boolean | null
NUMBER_RE.test(str) // number
) {
return false
}
return true
}
function addAttr (el, name, value) {
el.attrsMap[name] = value
el.attrsList.push({
name,
value
})
}
function updateEleId (el, it) {
if (el.type !== 1) {
return
}
const id = el.attrsMap[ID]
const newId = Number.isInteger(id) ? `("${id}-"+${it})` : `(${id}+${it})`
addAttr(el, ID, newId)
const attr = el.attrs.find(attr => attr.name === ID)
attr.value = newId
el.children.forEach(child => {
updateEleId(child, it)
})
}
function getBindingAttr (el, name) {
return getAndRemoveAttr(el, ':' + name) ||
getAndRemoveAttr(el, 'v-bind:' + name)
}
function getAndRemoveAttr (el, name) {
let val
if ((val = el.attrsMap[name]) != null) {
const list = el.attrsList
for (let i = 0, l = list.length; i < l; i++) {
if (list[i].name === name) {
list.splice(i, 1)
break
}
}
}
delete el.attrsMap[name]
return val
}
function updateForEleId (el) {
if (el.for) {
if (!el.iterator1) {
el.iterator1 = ITERATOR
}
updateEleId(el, el.iterator2 || el.iterator1)
}
}
function getForEl (el) {
if (el.for) {
return el
}
if (el.parent && el.parent.for && el.parent.tag === 'template') {
return el.parent
}
}
function processForKey (el) {
const forEl = getForEl(el)
if (forEl && !el.key) {
if (!isVar(forEl.for)) { // <view v-for="10"></view>
return
}
const it = forEl.iterator2 || forEl.iterator1 || ITERATOR
if (forEl.tag === 'template') {
if (forEl !== el) {
const keyIndex = forEl.children.indexOf(el)
el.key = `'${forEl.forId}-${keyIndex}-'+${it}`
} else { // 当 template 下只有文本节点
if (el.children && el.children.length && !el.children.find(child => child.key)) {
el.children[0].key = `'${forEl.forId}-0-'+${it}`
return true
}
}
} else {
el.key = `'${forEl.forId}-'+${it}`
}
}
}
module.exports = {
ID,
DATA_ROOT,
ITERATOR,
isVar,
addAttr,
getForEl,
processForKey,
updateForEleId,
getBindingAttr,
getAndRemoveAttr
}
const {
ID,
DATA_ROOT,
isVar,
getForEl,
updateForEleId,
processForKey
} = require('./util')
const parseText = require('./text-parser')
const preTransformNode = require('./pre-transform-node')
function createGenVar (id) {
return function genVar (name, extra = '') {
if (/^\d+$/.test(id)) {
return `${DATA_ROOT}['${id}']['${name}']${extra}`
}
return `${DATA_ROOT}[${id}]['${name}']${extra}`
}
}
// if 使用该方案是因为 template 节点之类无法挂靠 extras
function processIfConditions (el) {
if (el.if) {
el.ifConditions.forEach(con => {
if (isVar(con.exp)) {
con.exp = createGenVar(con.block.attrsMap[ID])(con.block.elseif ? 'v-else-if' : 'v-if')
}
})
el.if = createGenVar(el.attrsMap[ID])('v-if')
}
el.children && el.children.forEach(child => {
processIfConditions(child)
})
el.scopedSlots && Object.values(el.scopedSlots).forEach(child => {
processIfConditions(child)
})
}
function processBinding (el, genVar) {
if (el.classBinding) {
el.classBinding = genVar('c')
}
if (el.styleBinding) {
el.styleBinding = genVar('s')
}
}
function processFor (el, genVal) {
if (el.for && isVar(el.for)) {
el.for = createGenVar(el.forId)('v-for')
// <div><li v-for=" { a, b } in items"></li></div>
// =>
// <div><li v-for="$item in items"></li></div>
if (el.alias[0] === '{') {
el.alias = '$item'
}
// items 只有两种格式 [1,2,3],[{k0:'1-0',k1:'1-1'}]
// <div><li v-for="(item,key,index) in items"></li></div>
// =>
// <div><li v-for="(item,index) in items"></li></div>
if (el.iterator2) {
el.iterator1 = el.iterator2
delete el.iterator2
}
}
}
function processKey (el) {
// add default key
processForKey(el)
if (el.key) { // renderList key
const forEl = getForEl(el)
if (forEl) {
if (!isVar(forEl.for)) {
return
}
if (forEl === el) { // <view v-for="item in items" :key="item.id"></view>
el.key = forEl.alias
} else { // <template v-for="item in items"><view :key="item.id+'1'"></view><view :key="item.id+'2'"></view></template>
const keyIndex = forEl.children.indexOf(el)
el.key = `${forEl.alias}['k${keyIndex}']`
}
} else {
isVar(el.key) && (el.key = createGenVar(el.attrsMap[ID])('a-key'))
}
}
}
function processIf (el) {
// 因为时机问题,在最后处理根节点时,遍历处理 ifConditions
!el.parent && processIfConditions(el)
}
function processDirs (el, genVar) {
if (el.directives) {
el.directives.forEach(dir => {
dir.value && (dir.value = genVar('v-' + dir.name))
dir.isDynamicArg && (dir.arg = genVar('v-' + dir.name + '-arg'))
})
}
}
function processAttrs (el, genVar) {
el.attrs.forEach(attr => {
attr.name !== ID && isVar(attr.value) && (attr.value = genVar('a-' + attr.name))
})
}
function processProps (el, genVar) {
el.props && el.props.forEach(prop => {
isVar(prop.value) && (prop.value = genVar('a-' + prop.name))
})
}
function processText (el, genVar) {
const state = {
index: 0,
view: true,
genVar
}
el.children.forEach(child => {
if (child.type === 2) { // ASTExpression
child.expression = parseText(child.text, false, state).expression
}
})
}
function postTransformNode (el) {
updateForEleId(el)
const id = el.attrsMap[ID]
const genVar = createGenVar(id)
processFor(el, genVar)
processKey(el)
processIf(el)
processBinding(el, genVar)
processDirs(el, genVar)
processAttrs(el, genVar)
processProps(el, genVar)
processText(el, genVar)
}
function processEvents (events) {
Object.keys(events).forEach(name => {
const modifiers = Object.create(null)
let type = name
const isPassive = type.charAt(0) === '&'
type = isPassive ? type.slice(1) : type
const isOnce = type.charAt(0) === '~'
type = isOnce ? type.slice(1) : type
const isCapture = type.charAt(0) === '!'
type = isCapture ? type.slice(1) : type
isPassive && (modifiers.passive = true)
isOnce && (modifiers.once = true)
isCapture && (modifiers.capture = true)
const eventOpts = events[name]
if (Array.isArray(eventOpts)) {
eventOpts.forEach(eventOpt => {
eventOpt.modifiers && Object.assign(modifiers, eventOpt.modifiers)
})
} else {
eventOpts.modifiers && Object.assign(modifiers, eventOpts.modifiers)
}
if (Object.keys(modifiers).length) {
events[name] = {
value: `$handleViewEvent($event,${JSON.stringify(modifiers)})`
}
} else {
events[name] = {
value: `$handleViewEvent($event)`
}
}
})
}
function genData (el) {
if (el.model) {
el.model.callback = `function ($$v) {}`
}
// 放在 postTransformNode 中处理的时机太靠前,v-model 等指令会新增 event
// 理想情况,应该移除自定义组件的 events 配置,但目前不太好准确确定是自定义组件
el.events && processEvents(el.events)
el.nativeEvents && processEvents(el.nativeEvents)
return ''
}
module.exports = {
preTransformNode,
postTransformNode,
genData
}
......@@ -23,7 +23,23 @@ const compilerAlipayModule = require('./module-alipay')
const generateCodeFrame = require('./codeframe')
module.exports = {
compile (source, options = {}) {
compile (source, options = {}) {
if (options.service) {
(options.modules || (options.modules = [])).push(require('./app/service'))
options.optimize = true // 启用 staticRenderFns
// domProps => attrs
options.mustUseProp = () => false
// clear staticRenderFns
const compiled = compile(source, options)
compiled.staticRenderFns.length = 0
return compiled
} else if (options.view) {
(options.modules || (options.modules = [])).push(require('./app/view'))
options.optimize = false // 暂不启用 staticRenderFns
return compile(source, options)
}
if (!options.mp) { // h5
return compile(source, options)
}
......
......@@ -10,6 +10,20 @@ class WebpackAppPlusPlugin {
apply(compiler) {
compiler.hooks.done.tapPromise('WebpackAppPlusPlugin', compilation => {
return new Promise((resolve, reject) => {
if (process.env.UNI_USING_NATIVE) {
return resolve()
}
if (process.env.UNI_USING_V3) {
log()
if (process.env.NODE_ENV === 'development') {
done(`Build complete. Watching for changes...`)
} else {
done(`Build complete. `)
}
return resolve()
}
const callback = function() {
fs.copyFileSync(path.resolve(process.env.UNI_OUTPUT_TMP_DIR,
'manifest.json'),
......@@ -22,10 +36,6 @@ class WebpackAppPlusPlugin {
}
resolve()
}
if (process.env.UNI_USING_NATIVE) {
return resolve()
}
// Copy manifest.json
const wxmp = require(path.resolve(process.env.UNI_HBUILDERX_PLUGINS,
'weapp-tools/lib'))
......@@ -45,4 +55,4 @@ class WebpackAppPlusPlugin {
}
}
module.exports = WebpackAppPlusPlugin
module.exports = WebpackAppPlusPlugin
const path = require('path')
const {
runByHBuilderX
} = require('@dcloudio/uni-cli-shared')
......@@ -41,29 +43,8 @@ module.exports = (api, options) => {
})
}
async function build (args, api, options) {
const fs = require('fs-extra')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
function getWebpackConfig (api, args, options) {
const validateWebpackConfig = require('@vue/cli-service/lib/util/validateWebpackConfig')
const {
log,
done,
logWithSpinner,
stopSpinner
} = require('@vue/cli-shared-utils')
const runByAliIde = process.env.BUILD_ENV === 'ali-ide'
log()
if (!runByHBuilderX && !runByAliIde) {
logWithSpinner(`开始编译当前项目至 ${process.env.UNI_PLATFORM} 平台...`)
}
const targetDir = api.resolve(options.outputDir)
// resolve raw webpack config
const webpackConfig = require('@vue/cli-service/lib/commands/build/resolveAppConfig')(api, args, options)
......@@ -86,6 +67,47 @@ async function build (args, api, options) {
config.optimization.namedModules = false
})
}
return webpackConfig
}
function getWebpackConfigs (api, args, options) {
if (!process.env.UNI_USING_V3) {
return [getWebpackConfig(api, args, options)]
}
const pluginOptions = (options.pluginOptions || (options.pluginOptions = {}))
pluginOptions['uni-app-plus'] = {
service: true
}
const serviceWebpackConfig = getWebpackConfig(api, args, options)
delete pluginOptions['uni-app-plus']['service']
pluginOptions['uni-app-plus']['view'] = true
const viewWebpackConfig = getWebpackConfig(api, args, options)
return [serviceWebpackConfig, viewWebpackConfig]
}
async function build (args, api, options) {
const fs = require('fs-extra')
const chalk = require('chalk')
const webpack = require('webpack')
const {
log,
done,
logWithSpinner,
stopSpinner
} = require('@vue/cli-shared-utils')
const runByAliIde = process.env.BUILD_ENV === 'ali-ide'
log()
if (!runByHBuilderX && !runByAliIde) {
logWithSpinner(`开始编译当前项目至 ${process.env.UNI_PLATFORM} 平台...`)
}
const targetDir = api.resolve(options.outputDir)
const webpackConfigs = getWebpackConfigs(api, args, options)
if (process.env.NODE_ENV === 'production') {
try {
......@@ -97,8 +119,6 @@ async function build (args, api, options) {
await fs.emptyDir(targetDir)
}
const webpackConfigs = [webpackConfig]
if (process.env.UNI_USING_NATIVE) {
webpackConfigs.length = 0
}
......
......@@ -26,7 +26,7 @@ module.exports = (api, options) => {
require('./lib/options')(options)
api.configureWebpack(require('./lib/configure-webpack')(platformOptions, manifestPlatformOptions, options))
api.chainWebpack(require('./lib/chain-webpack')(platformOptions))
api.chainWebpack(require('./lib/chain-webpack')(platformOptions, options))
}
module.exports.defaultModes = {
......
const mp = require('../mp')
module.exports = mp
const path = require('path')
const webpack = require('webpack')
const {
getMainEntry,
getPlatformCompiler
} = require('@dcloudio/uni-cli-shared')
const {
isUnaryTag
} = require('../util')
function getProvides() {
return {
'__f__': [path.resolve(__dirname, '../format-log.js'), 'default']
}
}
const v3 = {
vueConfig: {
parallel: false
},
webpackConfig(webpackConfig, vueOptions) {
const isAppService = !!vueOptions.pluginOptions['uni-app-plus']['service']
const isAppView = !!vueOptions.pluginOptions['uni-app-plus']['view']
const statCode = process.env.UNI_USING_STAT ? `import '@dcloudio/uni-stat';` : ''
const beforeCode = `import 'uni-pages';`
if (!webpackConfig.optimization) {
webpackConfig.optimization = {}
}
// disable noEmitOnErrors
webpackConfig.optimization.noEmitOnErrors = false
if (isAppService) {
webpackConfig.optimization.runtimeChunk = {
name: 'app-config'
}
} else if (isAppView) {
webpackConfig.optimization.runtimeChunk = false
}
webpackConfig.optimization.splitChunks = false
let devtool = false
return {
devtool,
mode: process.env.NODE_ENV,
externals: {
vue: 'Vue'
},
entry() {
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())
}
return entry
},
output: {
filename: '[name].js',
chunkFilename: '[id].js'
},
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 ? 'wrap-loader' : path.resolve(__dirname,
'../../packages/webpack-uni-view-main-loader'),
options: {
before: [
beforeCode + statCode
]
}
}]
}]
},
plugins: [
new webpack.ProvidePlugin(getProvides())
]
}
},
chainWebpack(webpackConfig, vueOptions) {
const isAppService = !!vueOptions.pluginOptions['uni-app-plus']['service']
const isAppView = !!vueOptions.pluginOptions['uni-app-plus']['view']
const compilerOptions = {
isUnaryTag,
preserveWhitespace: false,
service: isAppService,
view: isAppView
}
// disable vue cache-loader
webpackConfig.module
.rule('vue')
.test([/\.vue$/, /\.nvue$/])
.use('vue-loader')
.loader(path.resolve(__dirname, '../../packages/vue-loader/lib'))
.tap(options => Object.assign(options, {
isAppView,
compiler: getPlatformCompiler(),
compilerOptions,
cacheDirectory: false,
cacheIdentifier: false
}))
.end()
.uses
.delete('cache-loader')
// .end()
// .use('uniapp-custom-block-loader')
// .loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-custom-block-loader'))
// .options({
// compiler: getPlatformCompiler()
// })
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')
}
......@@ -8,7 +8,7 @@ function resolve (dir) {
return path.resolve(__dirname, '..', dir)
}
module.exports = function chainWebpack (platformOptions) {
module.exports = function chainWebpack (platformOptions, vueOptions) {
const {
runByHBuilderX, // 使用 HBuilderX 运行
cssPreprocessOptions
......@@ -79,7 +79,7 @@ module.exports = function chainWebpack (platformOptions) {
})
}
platformOptions.chainWebpack(webpackConfig)
platformOptions.chainWebpack(webpackConfig, vueOptions)
// define
webpackConfig
.plugin('uni-define')
......
......@@ -14,12 +14,11 @@ function resolveModule (dir) {
return path.resolve(__dirname, '../../..', dir)
}
module.exports = function configureWebpack (platformOptions, manifestPlatformOptions, vueOptions) {
module.exports = function configureWebpack (platformOptions, manifestPlatformOptions, vueOptions) {
const {
runByHBuilderX, // 使用 HBuilderX 运行
isInHBuilderX, // 在 HBuilderX 的插件中
hasModule,
getMainEntry,
getPlatformVue,
jsPreprocessOptions,
htmlPreprocessOptions
......@@ -168,7 +167,7 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt
let platformWebpackConfig = platformOptions.webpackConfig
if (typeof platformWebpackConfig === 'function') {
platformWebpackConfig = platformWebpackConfig(webpackConfig)
platformWebpackConfig = platformWebpackConfig(webpackConfig, vueOptions)
}
// 移除 node_modules 目录,避免受路径上的 node_modules 影响
webpackConfig.resolve.modules = webpackConfig.resolve.modules.filter(module => module !==
......@@ -197,26 +196,6 @@ 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: [{
......@@ -226,18 +205,6 @@ 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: [{
......
......@@ -111,6 +111,17 @@ if (process.env.UNI_PLATFORM === 'mp-qq') { // QQ小程序 强制自定义组件
let isNVueCompiler = false
if (process.env.UNI_PLATFORM === 'app-plus') {
if (platformOptions.renderer !== 'native' && // 非 native
(
platformOptions.compilerVersion === '3' ||
platformOptions.compilerVersion === 3
)
) {
process.env.UNI_USING_V3 = true
platformOptions.usingComponents = true
process.env.UNI_OUTPUT_TMP_DIR = ''
}
if (platformOptions.nvueCompiler === 'uni-app') {
isNVueCompiler = true
}
......@@ -173,9 +184,9 @@ if (process.env.UNI_USING_COMPONENTS) { // 是否启用分包优化
}
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)`
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
// 输出编译器版本等信息
......@@ -193,8 +204,8 @@ if (process.env.UNI_PLATFORM !== 'h5') {
}
const glob = require('glob')
if (glob.sync('pages/**/*.nvue', {
cwd: process.env.UNI_INPUT_DIR
}).length) {
cwd: process.env.UNI_INPUT_DIR
}).length) {
console.log(info)
console.log(modeText)
if (needWarning) {
......@@ -226,9 +237,9 @@ moduleAlias.addAlias('mpvue-template-compiler', '@dcloudio/vue-cli-plugin-uni/pa
if (runByHBuilderX) {
const oldError = console.error
console.error = function (msg) {
console.error = function(msg) {
if (typeof msg === 'string' && msg.includes(
'[BABEL] Note: The code generator has deoptimised the styling of')) {
'[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('[警告] `' + path.relative(process.env.UNI_INPUT_DIR, filePath) +
......
......@@ -61,7 +61,19 @@ if (devServer && Object.keys(devServer).length) {
module.exports = {
vueConfig,
webpackConfig (webpackConfig) {
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: {
......@@ -73,6 +85,16 @@ 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',
......
......@@ -27,6 +27,11 @@ 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']
......@@ -68,7 +73,7 @@ module.exports = {
webpackConfig.optimization.noEmitOnErrors = false
webpackConfig.optimization.runtimeChunk = {
name: 'common/runtime'
name: process.env.UNI_USING_V3 ? 'app-config' : 'common/runtime'
}
webpackConfig.optimization.splitChunks = require('./split-chunks')()
......@@ -93,10 +98,23 @@ 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: {
......@@ -104,9 +122,9 @@ module.exports = {
chunkFilename: '[id].js',
globalObject: process.env.UNI_PLATFORM === 'mp-alipay' ? 'my' : 'global',
sourceMapFilename: '../.sourcemap/' + process.env.UNI_PLATFORM + '/[name].js.map'
},
performance: {
hints: false
},
performance: {
hints: false
},
resolve: {
extensions: ['.nvue'],
......@@ -119,6 +137,13 @@ 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'
}]
}, {
......@@ -160,6 +185,15 @@ 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
}
// disable vue cache-loader
webpackConfig.module
.rule('vue')
......@@ -167,10 +201,7 @@ module.exports = {
.use('vue-loader')
.tap(options => Object.assign(options, {
compiler: getPlatformCompiler(),
compilerOptions: process.env.UNI_USING_COMPONENTS ? {
isUnaryTag,
preserveWhitespace: false
} : require('./mp-compiler-options'),
compilerOptions,
cacheDirectory: false,
cacheIdentifier: false
}))
......@@ -189,10 +220,12 @@ module.exports = {
const styleExt = getPlatformExts().style
webpackConfig.plugin('extract-css')
.init((Plugin, args) => new Plugin({
filename: '[name]' + styleExt
}))
if (!process.env.UNI_USING_V3) {
webpackConfig.plugin('extract-css')
.init((Plugin, args) => new Plugin({
filename: '[name]' + styleExt
}))
}
if (
process.env.NODE_ENV === 'production' &&
......
......@@ -33,7 +33,7 @@ module.exports = function initOptions (options) {
options.css = {}
}
if (process.env.UNI_PLATFORM === 'h5') {
if (process.env.UNI_PLATFORM === 'h5' || process.env.UNI_USING_V3) {
options.css.extract = false
} else {
options.css.extract = true
......
const path = require('path')
module.exports = function getSplitChunks () {
if (process.env.UNI_USING_V3) {
return false
}
if (!process.env.UNI_USING_COMPONENTS) {
return {
cacheGroups: {
......
<a name="4.1.2"></a>
## [4.1.2](https://github.com/vuejs/vue-style-loader/compare/v4.1.1...v4.1.2) (2018-08-13)
### Bug Fixes
* fix inconsistent hashes between Windows and POSIX systems ([#28](https://github.com/vuejs/vue-style-loader/issues/28)) ([cf8b6e8](https://github.com/vuejs/vue-style-loader/commit/cf8b6e8))
<a name="4.1.1"></a>
## [4.1.1](https://github.com/vuejs/vue-style-loader/compare/v4.1.0...v4.1.1) (2018-07-17)
### Bug Fixes
* fix addStyleShadow when same style object is inserted multiple times ([12846a6](https://github.com/vuejs/vue-style-loader/commit/12846a6))
<a name="4.1.0"></a>
# [4.1.0](https://github.com/vuejs/vue-style-loader/compare/v4.0.2...v4.1.0) (2018-03-20)
### Features
* support vue-loader 15 ([0c7ee9d](https://github.com/vuejs/vue-style-loader/commit/0c7ee9d))
<a name="4.0.2"></a>
## [4.0.2](https://github.com/vuejs/vue-style-loader/compare/v4.0.1...v4.0.2) (2018-02-13)
<a name="4.0.1"></a>
## [4.0.1](https://github.com/vuejs/vue-style-loader/compare/v4.0.0...v4.0.1) (2018-01-31)
### Bug Fixes
* typo ([00087b7](https://github.com/vuejs/vue-style-loader/commit/00087b7))
<a name="4.0.0"></a>
# [4.0.0](https://github.com/vuejs/vue-style-loader/compare/v3.1.1...v4.0.0) (2018-01-31)
### Features
* shadowMode ([94737e5](https://github.com/vuejs/vue-style-loader/commit/94737e5))
* use ESM for runtime files ([18d0ae4](https://github.com/vuejs/vue-style-loader/commit/18d0ae4))
<a name="3.1.1"></a>
## [3.1.1](https://github.com/vuejs/vue-style-loader/compare/v3.1.0...v3.1.1) (2018-01-24)
<a name="3.1.0"></a>
# [3.1.0](https://github.com/vuejs/vue-style-loader/compare/v3.0.3...v3.1.0) (2018-01-24)
### Features
* add `ssrId` option for rendering ssr id on client ([5281305](https://github.com/vuejs/vue-style-loader/commit/5281305))
Copyright JS Foundation and other contributors
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.
# vue-style-loader [![Build Status](https://circleci.com/gh/vuejs/vue-style-loader/tree/master.svg?style=shield)](https://circleci.com/gh/vuejs/vue-loader/tree/master) [![npm package](https://img.shields.io/npm/v/vue-style-loader.svg)](https://www.npmjs.com/package/vue-style-loader)
This is a fork based on [style-loader](https://github.com/webpack/style-loader). Similar to `style-loader`, you can chain it after `css-loader` to dynamically inject CSS into the document as style tags. However, since this is included as a dependency and used by default in `vue-loader`, in most cases you don't need to configure this loader yourself.
## Options
- **manualInject** (3.1.0+):
Type: `boolean`. When importing the style from a non-vue-file, by default the style is injected as a side effect of the import. When `manualInject` is true, the imported style object exposes a `__inject__` method, which can then be called manually at appropriate timing. If called on the server, the method expects one argument which is the `ssrContext` to attach styles to.
``` js
import styles from 'styles.scss'
export default {
beforeCreate() { // or create a mixin for this purpose
if(styles.__inject__) {
styles.__inject__(this.$ssrContext)
}
}
render() {
return <div class={styles.heading}>Hello World</div>
}
}
```
Note this behavior is enabled automatically when `vue-style-loader` is used on styles imported within a `*.vue` file. The option is only exposed for advanced usage.
- **ssrId** (3.1.0+):
Type: `boolean`. Add `data-vue-ssr-id` attribute to injected `<style>` tags even when not in Node.js. This can be used with pre-rendering (instead of SSR) to avoid duplicate style injection on hydration.
## Differences from `style-loader`
### Server-Side Rendering Support
When bundling with `target: 'node'`, the styles in all rendered components are collected and exposed on the Vue render context object as `context.styles`, which you can simply inline into your markup's `<head>`. If you are building a Vue SSR app, you probably should use this loader for CSS imported from JavaScript files too.
### Misc
- Does not support url mode and reference counting mode. Also removed `singleton` and `insertAt` query options. It always automatically pick the style insertion mechanism that makes most sense. If you need these capabilities you should probably use the original `style-loader` instead.
- Fixed the issue that root-relative URLs are interpreted against chrome:// urls and make source map URLs work for injected `<style>` tags in Chrome.
## License
MIT
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
Modified by Evan You @yyx990803
*/
var loaderUtils = require('loader-utils')
var path = require('path')
var hash = require('hash-sum')
var qs = require('querystring')
module.exports = function () {}
module.exports.pitch = function (remainingRequest) {
var isServer = this.target === 'node'
var isProduction = this.minimize || process.env.NODE_ENV === 'production'
var addStylesClientPath = loaderUtils.stringifyRequest(this, '!' + path.join(__dirname, 'lib/addStylesClient.js'))
var addStylesServerPath = loaderUtils.stringifyRequest(this, '!' + path.join(__dirname, 'lib/addStylesServer.js'))
var addStylesShadowPath = loaderUtils.stringifyRequest(this, '!' + path.join(__dirname, 'lib/addStylesShadow.js'))
var request = loaderUtils.stringifyRequest(this, '!!' + remainingRequest)
var relPath = path.relative(__dirname, this.resourcePath).replace(/\\/g, '/')
var id = JSON.stringify(hash(request + relPath))
var options = loaderUtils.getOptions(this) || {}
// direct css import from js --> direct, or manually call `styles.__inject__(ssrContext)` with `manualInject` option
// css import from vue file --> component lifecycle linked
// style embedded in vue file --> component lifecycle linked
var isVue = (
/"vue":true/.test(remainingRequest) ||
options.manualInject ||
qs.parse(this.resourceQuery.slice(1)).vue != null
)
var shared = [
'// style-loader: Adds some css to the DOM by adding a <style> tag',
'',
'// load the styles',
'var content = require(' + request + ');',
// content list format is [id, css, media, sourceMap]
"if(typeof content === 'string') content = [[module.id, content, '']];",
'if(content.locals) module.exports = content.locals;'
]
// shadowMode is enabled in vue-cli with vue build --target web-component.
// exposes the same __inject__ method like SSR
if (options.shadowMode) {
return shared.concat([
'// add CSS to Shadow Root',
'var add = require(' + addStylesShadowPath + ').default',
'module.exports.__inject__ = function (shadowRoot) {',
' add(' + id + ', content, shadowRoot)',
'};'
]).join('\n')
} else if (!isServer) {
// on the client: dynamic inject + hot-reload
var code = [
'// add the styles to the DOM',
'var add = require(' + addStylesClientPath + ').default',
'var update = add(' + id + ', content, ' + isProduction + ', ' + JSON.stringify(options) + ');'
]
if (!isProduction) {
code = code.concat([
'// Hot Module Replacement',
'if(module.hot) {',
' // When the styles change, update the <style> tags',
' if(!content.locals) {',
' module.hot.accept(' + request + ', function() {',
' var newContent = require(' + request + ');',
" if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];",
' update(newContent);',
' });',
' }',
' // When the module is disposed, remove the <style> tags',
' module.hot.dispose(function() { update(); });',
'}'
])
}
return shared.concat(code).join('\n')
} else {
// on the server: attach to Vue SSR context
if (isVue) {
// inside *.vue file: expose a function so it can be called in
// component's lifecycle hooks
return shared.concat([
'// add CSS to SSR context',
'var add = require(' + addStylesServerPath + ').default',
'module.exports.__inject__ = function (context) {',
' add(' + id + ', content, ' + isProduction + ', context)',
'};'
]).join('\n')
} else {
// normal import
return shared.concat([
'require(' + addStylesServerPath + ').default(' + id + ', content, ' + isProduction + ')'
]).join('\n')
}
}
}
import listToStyles from './listToStyles'
export default function addStylesServer (parentId, list, isProduction, context) {
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
context = __VUE_SSR_CONTEXT__
}
if (context) {
if (!context.hasOwnProperty('styles')) {
Object.defineProperty(context, 'styles', {
enumerable: true,
get: function() {
return renderStyles(context._styles)
}
})
// expose renderStyles for vue-server-renderer (vuejs/#6353)
context._renderStyles = renderStyles
}
var styles = context._styles || (context._styles = {})
list = listToStyles(parentId, list)
if (isProduction) {
addStyleProd(styles, list)
} else {
addStyleDev(styles, list)
}
}
}
// In production, render as few style tags as possible.
// (mostly because IE9 has a limit on number of style tags)
function addStyleProd (styles, list) {
for (var i = 0; i < list.length; i++) {
var parts = list[i].parts
for (var j = 0; j < parts.length; j++) {
var part = parts[j]
// group style tags by media types.
var id = part.media || 'default'
var style = styles[id]
if (style) {
if (style.ids.indexOf(part.id) < 0) {
style.ids.push(part.id)
style.css += '\n' + part.css
}
} else {
styles[id] = {
ids: [part.id],
css: part.css,
media: part.media
}
}
}
}
}
// In dev we use individual style tag for each module for hot-reload
// and source maps.
function addStyleDev (styles, list) {
for (var i = 0; i < list.length; i++) {
var parts = list[i].parts
for (var j = 0; j < parts.length; j++) {
var part = parts[j]
styles[part.id] = {
ids: [part.id],
css: part.css,
media: part.media
}
}
}
}
function renderStyles (styles) {
var css = ''
for (var key in styles) {
var style = styles[key]
css += '<style data-vue-ssr-id="' + style.ids.join(' ') + '"' +
(style.media ? ( ' media="' + style.media + '"' ) : '') + '>' +
style.css + '</style>'
}
return css
}
import listToStyles from './listToStyles'
export default function addStylesToShadowDOM (parentId, list, shadowRoot) {
var styles = listToStyles(parentId, list)
addStyles(styles, shadowRoot)
}
/*
type StyleObject = {
id: number;
parts: Array<StyleObjectPart>
}
type StyleObjectPart = {
css: string;
media: string;
sourceMap: ?string
}
*/
function addStyles (styles /* Array<StyleObject> */, shadowRoot) {
const injectedStyles =
shadowRoot._injectedStyles ||
(shadowRoot._injectedStyles = {})
for (var i = 0; i < styles.length; i++) {
var item = styles[i]
var style = injectedStyles[item.id]
if (!style) {
for (var j = 0; j < item.parts.length; j++) {
addStyle(item.parts[j], shadowRoot)
}
injectedStyles[item.id] = true
}
}
}
function createStyleElement (shadowRoot) {
var styleElement = document.createElement('style')
styleElement.type = 'text/css'
shadowRoot.appendChild(styleElement)
return styleElement
}
function addStyle (obj /* StyleObjectPart */, shadowRoot) {
var styleElement = createStyleElement(shadowRoot)
var css = obj.css
var media = obj.media
var sourceMap = obj.sourceMap
if (media) {
styleElement.setAttribute('media', media)
}
if (sourceMap) {
// https://developer.chrome.com/devtools/docs/javascript-debugging
// this makes source maps inside style tags work properly in Chrome
css += '\n/*# sourceURL=' + sourceMap.sources[0] + ' */'
// http://stackoverflow.com/a/26603875
css += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + ' */'
}
if (styleElement.styleSheet) {
styleElement.styleSheet.cssText = css
} else {
while (styleElement.firstChild) {
styleElement.removeChild(styleElement.firstChild)
}
styleElement.appendChild(document.createTextNode(css))
}
}
/**
* Translates the list format produced by css-loader into something
* easier to manipulate.
*/
export default function listToStyles (parentId, list) {
var styles = []
var newStyles = {}
for (var i = 0; i < list.length; i++) {
var item = list[i]
var id = item[0]
var css = item[1]
var media = item[2]
var sourceMap = item[3]
var part = {
id: parentId + ':' + i,
css: css,
media: media,
sourceMap: sourceMap
}
if (!newStyles[id]) {
styles.push(newStyles[id] = { id: id, parts: [part] })
} else {
newStyles[id].parts.push(part)
}
}
return styles
}
此差异已折叠。
module.exports = function(source, map) {
return `import 'uni-pages';
UniViewJSBridge.publishHandler('webviewReady')
`
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册