From 848606b98cd58fa2b9e8ab9b71fa4ce6054cf9bc Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Fri, 13 Mar 2020 19:12:57 +0800 Subject: [PATCH] feat(cli): normalize absolute paths in css URLs --- .eslintignore | 1 - packages/uni-cli-shared/lib/manifest.js | 3 +- packages/uni-cli-shared/lib/url-loader.js | 64 +++++++++++++++++++ packages/uni-cli-shared/package.json | 1 + .../uni-template-compiler/lib/asset-url.js | 14 ++-- .../build/css-loader.conf.js | 27 +++++--- .../build/vue-loader.conf.js | 3 + .../vue-cli-plugin-uni/lib/app-plus/index.js | 35 +--------- .../vue-cli-plugin-uni/lib/chain-webpack.js | 7 +- .../lib/configure-webpack.js | 1 + packages/vue-cli-plugin-uni/lib/env.js | 1 - .../packages/postcss/index.js | 32 ++++++---- .../packages/postcss/index.v3.js | 12 +++- .../app-plus/service/framework/app.js | 6 +- 14 files changed, 133 insertions(+), 74 deletions(-) create mode 100644 packages/uni-cli-shared/lib/url-loader.js diff --git a/.eslintignore b/.eslintignore index 0005864c..a8fd5a7d 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,4 +4,3 @@ build/rollup-plugin-require-context packages/*/packages packages/*/template/**/* qh-api.js -touch-emulator.js diff --git a/packages/uni-cli-shared/lib/manifest.js b/packages/uni-cli-shared/lib/manifest.js index 0d50f77c..2751be1e 100644 --- a/packages/uni-cli-shared/lib/manifest.js +++ b/packages/uni-cli-shared/lib/manifest.js @@ -75,8 +75,7 @@ function getH5Options (manifestJson) { if (!h5.publicPath.endsWith('/')) { h5.publicPath = h5.publicPath + '/' } - } else { // 其他模式,启用 base - + } else { // 其他模式,启用 base if (base.startsWith('./')) { // 在开发模式, publicPath 如果为 './' webpack-dev-server 匹配文件时会失败 h5.publicPath = base.substr(1) diff --git a/packages/uni-cli-shared/lib/url-loader.js b/packages/uni-cli-shared/lib/url-loader.js new file mode 100644 index 00000000..e274352a --- /dev/null +++ b/packages/uni-cli-shared/lib/url-loader.js @@ -0,0 +1,64 @@ +const path = require('path') + +const defaultOptions = { + limit: -1, + fallback: { + loader: 'file-loader', + options: { + publicPath (url, resourcePath, context) { + if ( + process.env.UNI_PLATFORM === 'app-plus' && + process.env.UNI_USING_V3 + ) { // app-plus v3 下路径不能以/开头 + return path.relative(process.env.UNI_INPUT_DIR, resourcePath) + } + return '/' + path.relative(process.env.UNI_INPUT_DIR, resourcePath) + }, + outputPath (url, resourcePath, context) { + return path.relative(process.env.UNI_INPUT_DIR, resourcePath) + } + } + } +} + +const inlineLimit = + process.env.UNI_PLATFORM === 'mp-weixin' || + process.env.UNI_PLATFORM === 'mp-qq' || + process.env.UNI_PLATFORM === 'mp-toutiao' || + process.env.UNI_PLATFORM === 'app-plus' // v2需要base64,v3需要rewriteUrl + +// mp-weixin,mp-qq,app-plus 非v3(即:需要base64的平台) +// 将/static/logo.png转换为~@/static/logo.png +// @import,src,background,background-image + +const rewriteUrl = inlineLimit ? require('postcss-urlrewrite')({ + imports: true, + properties: ['src', 'background', 'background-image'], + rules: [{ + from: /^@\//, + to: '~@/' + }, { + from: /^\/([^/])/, + to: '~@/$1' + }] +}) : () => {} + +module.exports = { + loader: 'url-loader', + options () { + if (process.env.UNI_PLATFORM === 'h5') { + // h5平台,不对 url-loader 作调整,默认limit:4096,也不修改file-loader输出路径 + return {} + } + if (inlineLimit) { + return { + ...defaultOptions, + limit: process.env.UNI_USING_V3 ? -1 : 40960 // (主要用于background-image) + } + } + return { + ...defaultOptions + } + }, + rewriteUrl +} diff --git a/packages/uni-cli-shared/package.json b/packages/uni-cli-shared/package.json index 862decda..14ed8ca1 100644 --- a/packages/uni-cli-shared/package.json +++ b/packages/uni-cli-shared/package.json @@ -20,6 +20,7 @@ "license": "Apache-2.0", "dependencies": { "hash-sum": "^1.0.2", + "postcss-urlrewrite": "^0.2.2", "strip-json-comments": "^2.0.1" }, "gitHead": "84e9cb1ca1898054d161f1514efadd1ab24fd804" diff --git a/packages/uni-template-compiler/lib/asset-url.js b/packages/uni-template-compiler/lib/asset-url.js index 5a56ddc8..4e7232bf 100644 --- a/packages/uni-template-compiler/lib/asset-url.js +++ b/packages/uni-template-compiler/lib/asset-url.js @@ -3,11 +3,15 @@ const transformAssetUrls = { 'video': ['src', 'poster'], 'img': 'src', 'image': 'src', - 'cover-image': 'src', - 'v-uni-audio': 'src', - 'v-uni-video': ['src', 'poster'], - 'v-uni-image': 'src', - 'v-uni-cover-image': 'src' + 'cover-image': 'src', + // h5 + 'v-uni-audio': 'src', + 'v-uni-video': ['src', 'poster'], + 'v-uni-image': 'src', + 'v-uni-cover-image': 'src', + // nvue + 'u-image': 'src', + 'u-video': ['src', 'poster'] } function rewrite (attr, name) { diff --git a/packages/vue-cli-plugin-hbuilderx/build/css-loader.conf.js b/packages/vue-cli-plugin-hbuilderx/build/css-loader.conf.js index 7cf75ecb..87cfac9e 100644 --- a/packages/vue-cli-plugin-hbuilderx/build/css-loader.conf.js +++ b/packages/vue-cli-plugin-hbuilderx/build/css-loader.conf.js @@ -25,8 +25,19 @@ const postcssLoader = { options: { sourceMap: false, parser: require('postcss-comment'), - plugins: [ - require('postcss-import'), + plugins: [ + require('postcss-import')({ + resolve (id, basedir, importOptions) { + if (id.startsWith('~@/')) { + return path.resolve(process.env.UNI_INPUT_DIR, id.substr(3)) + } else if (id.startsWith('@/')) { + return path.resolve(process.env.UNI_INPUT_DIR, id.substr(2)) + } else if (id.startsWith('/') && !id.startsWith('//')) { + return path.resolve(process.env.UNI_INPUT_DIR, id.substr(1)) + } + return id + } + }), require('@dcloudio/vue-cli-plugin-uni/packages/postcss') ] } @@ -59,17 +70,17 @@ const sassLoader = { } if (sassLoaderVersion < 8) { - scssLoader.options.data = sassData - scssLoader.options.outputStyle = 'nested' + scssLoader.options.data = sassData + scssLoader.options.outputStyle = 'nested' sassLoader.options.data = sassData sassLoader.options.outputStyle = 'nested' sassLoader.options.indentedSyntax = true } else { - scssLoader.options.prependData = sassData - scssLoader.options.sassOptions = { - outputStyle: 'nested' - } + scssLoader.options.prependData = sassData + scssLoader.options.sassOptions = { + outputStyle: 'nested' + } sassLoader.options.prependData = sassData sassLoader.options.sassOptions = { diff --git a/packages/vue-cli-plugin-hbuilderx/build/vue-loader.conf.js b/packages/vue-cli-plugin-hbuilderx/build/vue-loader.conf.js index d87bf1bc..8cf218c8 100644 --- a/packages/vue-cli-plugin-hbuilderx/build/vue-loader.conf.js +++ b/packages/vue-cli-plugin-hbuilderx/build/vue-loader.conf.js @@ -104,6 +104,9 @@ const compiler = require('weex-template-compiler') const oldCompile = compiler.compile compiler.compile = function (source, options = {}) { (options.modules || (options.modules = [])).push(autoComponentsModule) + + options.modules.push(require('@dcloudio/uni-template-compiler/lib/asset-url')) + options.isUnaryTag = isUnaryTag // 将 autoComponents 挂在 isUnaryTag 上边 options.isUnaryTag.autoComponents = new Set() diff --git a/packages/vue-cli-plugin-uni/lib/app-plus/index.js b/packages/vue-cli-plugin-uni/lib/app-plus/index.js index 81e1d191..a56a943e 100644 --- a/packages/vue-cli-plugin-uni/lib/app-plus/index.js +++ b/packages/vue-cli-plugin-uni/lib/app-plus/index.js @@ -2,8 +2,7 @@ const path = require('path') const webpack = require('webpack') const { - getMainEntry, - isInHBuilderX + getMainEntry } = require('@dcloudio/uni-cli-shared') const vueLoader = require('@dcloudio/uni-cli-shared/lib/vue-loader') @@ -200,38 +199,6 @@ const v3 = { const isAppService = !!vueOptions.pluginOptions['uni-app-plus']['service'] const isAppView = !!vueOptions.pluginOptions['uni-app-plus']['view'] - const fileLoaderOptions = isInHBuilderX ? { - emitFile: isAppView, - name: '[path][name].[ext]', - context: process.env.UNI_INPUT_DIR - } : { - emitFile: isAppView, - outputPath (url, resourcePath, context) { - return path.relative(process.env.UNI_INPUT_DIR, resourcePath) - } - } - - // 处理静态资源 - webpackConfig.module - .rule('svg') - .use('file-loader') - .options(fileLoaderOptions) - - const staticTypes = ['images', 'media', 'fonts'] - staticTypes.forEach(staticType => { - webpackConfig.module - .rule(staticType) - .use('url-loader') - .loader('url-loader') - .tap(options => Object.assign(options, { - limit: 1, - fallback: { - loader: 'file-loader', - options: fileLoaderOptions - } - })) - }) - const cacheConfig = { cacheDirectory: false, cacheIdentifier: false diff --git a/packages/vue-cli-plugin-uni/lib/chain-webpack.js b/packages/vue-cli-plugin-uni/lib/chain-webpack.js index 7031976b..f740073d 100644 --- a/packages/vue-cli-plugin-uni/lib/chain-webpack.js +++ b/packages/vue-cli-plugin-uni/lib/chain-webpack.js @@ -20,15 +20,14 @@ module.exports = function chainWebpack (platformOptions, vueOptions, api) { return function (webpackConfig) { // 处理静态资源 limit + const urlLoader = require('@dcloudio/uni-cli-shared/lib/url-loader') const staticTypes = ['images', 'media', 'fonts'] staticTypes.forEach(staticType => { webpackConfig.module .rule(staticType) .use('url-loader') - .loader('url-loader') - .tap(options => Object.assign(options, { - limit: 40960 - })) + .loader(urlLoader.loader) + .tap(options => Object.assign(options, urlLoader.options())) }) // 条件编译 vue 文件统一直接过滤html,js,css三种类型,单独资源文件引用各自过滤 diff --git a/packages/vue-cli-plugin-uni/lib/configure-webpack.js b/packages/vue-cli-plugin-uni/lib/configure-webpack.js index de7681b4..69143242 100644 --- a/packages/vue-cli-plugin-uni/lib/configure-webpack.js +++ b/packages/vue-cli-plugin-uni/lib/configure-webpack.js @@ -239,6 +239,7 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt resolve: { alias: { '@': path.resolve(process.env.UNI_INPUT_DIR), + './@': path.resolve(process.env.UNI_INPUT_DIR), // css中的'@/static/logo.png'会被转换成'./@/static/logo.png'加载 'vue$': getPlatformVue(vueOptions), 'uni-pages': path.resolve(process.env.UNI_INPUT_DIR, 'pages.json'), '@dcloudio/uni-stat': require.resolve('@dcloudio/uni-stat'), diff --git a/packages/vue-cli-plugin-uni/lib/env.js b/packages/vue-cli-plugin-uni/lib/env.js index e92a72a8..f5e8ebef 100644 --- a/packages/vue-cli-plugin-uni/lib/env.js +++ b/packages/vue-cli-plugin-uni/lib/env.js @@ -48,7 +48,6 @@ if ( console.warn(`发布H5,需要在uniCloud后台操作,绑定安全域名,否则会因为跨域问题而无法访问。教程参考:https://uniapp.dcloud.io/uniCloud/quickstart-H5`) } - // 初始化环境变量 const defaultInputDir = '../../../../src' const defaultOutputDir = '../../../../dist/' + diff --git a/packages/vue-cli-plugin-uni/packages/postcss/index.js b/packages/vue-cli-plugin-uni/packages/postcss/index.js index 0b78b257..c36ff7fd 100644 --- a/packages/vue-cli-plugin-uni/packages/postcss/index.js +++ b/packages/vue-cli-plugin-uni/packages/postcss/index.js @@ -150,6 +150,7 @@ if (process.env.UNI_USING_V3) { 'background-attachment' ] + let rewriteUrl /** * 转换 upx * 转换 px @@ -160,6 +161,11 @@ if (process.env.UNI_USING_V3) { ...opts } return function (root, result) { + if (!rewriteUrl) { + rewriteUrl = require('@dcloudio/uni-cli-shared/lib/url-loader').rewriteUrl + } + rewriteUrl(root) + if (process.env.UNI_PLATFORM === 'h5') { // Transform CSS AST here @@ -235,19 +241,19 @@ if (process.env.UNI_USING_V3) { // Transform each property declaration here decl.value = tranformValue(decl, opts) }) - if (process.env.UNI_PLATFORM !== 'quickapp') { - rule.selectors = rule.selectors.map(complexSelector => { - return transformSelector(complexSelector, simpleSelectors => { - return simpleSelectors.walkTags(tag => { - const k = tag.value - const v = CSS_TAGS[k] - if (v) { - tag.value = v === 'r' - ? `._${k}` : v - } - }) - }) - }) + if (process.env.UNI_PLATFORM !== 'quickapp') { + rule.selectors = rule.selectors.map(complexSelector => { + return transformSelector(complexSelector, simpleSelectors => { + return simpleSelectors.walkTags(tag => { + const k = tag.value + const v = CSS_TAGS[k] + if (v) { + tag.value = v === 'r' + ? `._${k}` : v + } + }) + }) + }) } }) } diff --git a/packages/vue-cli-plugin-uni/packages/postcss/index.v3.js b/packages/vue-cli-plugin-uni/packages/postcss/index.v3.js index 484d1998..0e71bc9e 100644 --- a/packages/vue-cli-plugin-uni/packages/postcss/index.v3.js +++ b/packages/vue-cli-plugin-uni/packages/postcss/index.v3.js @@ -11,8 +11,16 @@ const isInsideKeyframes = function (rule) { rule.parent && rule.parent.type === 'atrule' && /^(-\w+-)?keyframes$/.test(rule.parent.name) ) } + +let rewriteUrl + module.exports = postcss.plugin('postcss-uniapp-plugin', function (opts) { - return function (root, result) { + return function (root, result) { + if (!rewriteUrl) { + rewriteUrl = require('@dcloudio/uni-cli-shared/lib/url-loader').rewriteUrl + } + rewriteUrl(root) + root.walkRules(rule => { // Transform each rule here if (!isInsideKeyframes(rule)) { @@ -27,7 +35,7 @@ module.exports = postcss.plugin('postcss-uniapp-plugin', function (opts) { if (tag.value === 'page') { tag.value = 'body' } else if (~TAGS.indexOf(tag.value) && tag.value.substring( - 0, 4) !== 'uni-') { + 0, 4) !== 'uni-') { tag.value = 'uni-' + tag.value } }) diff --git a/src/platforms/app-plus/service/framework/app.js b/src/platforms/app-plus/service/framework/app.js index 19817960..2a17ea36 100644 --- a/src/platforms/app-plus/service/framework/app.js +++ b/src/platforms/app-plus/service/framework/app.js @@ -6,6 +6,8 @@ import initOn from 'uni-core/service/bridge/on' import { requireNativePlugin + , + publish } from '../bridge' import { @@ -22,10 +24,6 @@ import { import tabBar from './tab-bar' -import { - publish -} from '../bridge' - import { initSubscribeHandlers } from './subscribe-handlers' -- GitLab