vue3 + vite
vue3 下 , h5使用rpx 时, 会 编译成 rem
注册 postcss 的 plugin
在/node_modules/@dcloudio/uni-h5-vite/dist/plugin/config.js,
代码是, 用的 是config 这个钩子
css: {
postcss: {
plugins: (0, uni_cli_shared_1.initPostcssPlugin)({
uniApp: (0, uni_cli_shared_1.parseRpx2UnitOnce)(inputDir, process.env.UNI_PLATFORM),
}),
},
},
parseRpx2UnitOnce , 选定使用的单位
exports.parseRpx2UnitOnce = (0, uni_shared_1.once)((inputDir, platform = 'h5') => {
// 如果是 h5/app/鸿蒙 会使用 defaultRpx2Unit
const rpx2unit = platform === 'h5' || platform === 'app' || platform === 'app-harmony'
? uni_shared_1.defaultRpx2Unit
: uni_shared_1.defaultMiniProgramRpx2Unit;
const manifestJson = (0, exports.parseManifestJsonOnce)(inputDir);
let platformOptions = getPlatformManifestJson(manifestJson, platform);
if (platformOptions && platformOptions.rpx) {
return (0, shared_1.extend)({}, rpx2unit, platformOptions);
}
return (0, shared_1.extend)({}, rpx2unit);
});
都有啥呢 ?
const defaultRpx2Unit = {
unit: 'rem',
unitRatio: 10 / 320,
unitPrecision: 5,
};
const defaultMiniProgramRpx2Unit = {
unit: 'rpx',
unitRatio: 1,
unitPrecision: 1,
};
但是 注意这里 let platformOptions = getPlatformManifestJson(manifestJson, platform);
还是 会从 mainfest中 获取 配置的, 如果有 , 就用 mainfest 中的,
也就是 你可以 在 manifest.json的 h5节点下 , 覆盖 一些 配置 , 例如
"h5": {
"router": {
"mode": "history"
},
"unit": "px",
"unitRatio": 0.5,
"unitPrecision": 2,
}
但是 文档里 , 我没有 找到
哪里 修改的 rpx 2 rem 呢?
在这里 /node_modules/@dcloudio/uni-cli-shared/dist/postcss/plugins/uniapp.js
const uniapp = (opts) => {
const platform = process.env.UNI_PLATFORM;
const { unit, unitRatio, unitPrecision } = (0, shared_1.extend)({}, defaultUniAppCssProcessorOptions, opts);
const rpx2unit = (0, uni_shared_1.createRpx2Unit)(unit, unitRatio, unitPrecision);
return {
postcssPlugin: 'uni-app',
prepare() {
return {
OnceExit(root) {
root.walkDecls(walkDecls(rpx2unit));
const rewriteTag = transforms[platform];
filterPrefersColorScheme(root);
if (rewriteTag) {
root.walkRules(walkRules({
rewriteTag,
}));
}
},
};
},
};
};
就是 遍历 然后 替换
function walkDecls(rpx2unit) {
return (decl) => {
const { value } = decl;
if (value.indexOf('rpx') === -1 && value.indexOf('upx') === -1) {
return;
}
// 如果有 rpx 或者upx, 就调用rpx2unit
decl.value = rpx2unit(decl.value);
};
}
const unitRE = new RegExp(`"[^"]+"|'[^']+'|url\\([^)]+\\)|(\\d*\\.?\\d+)[r|u]px`, 'g');
// 这里的 参数 就是 defaultRpx2Unit的三个参数
function createRpx2Unit(unit, unitRatio, unitPrecision) {
// ignore: rpxCalcIncludeWidth
return (val) => val.replace(unitRE, (m, $1) => {
if (!$1) {
return m;
}
if (unitRatio === 1) {
return `${$1}${unit}`;
}
// 替换 为 rem
// 就是 * unitRatio, 然后 保留unitPrecision 位的小数
const value = toFixed(parseFloat($1) * unitRatio, unitPrecision);
return value === 0 ? '0' : `${value}${unit}`;
});
}
我是 分割线----------------------------------------------------------------------------------------------------------------------------------------------------------------
vue2 + webpack
再 说一下 vue2的 处理, vue2 是 依托于 vue-cli-service
查看打包结果
写一个 最简单的 项目,
查看 打包后的 结果
___CSS_LOADER_EXPORT___.push([
module.id,
'@charset "UTF-8";\n/**\n */.ggdxd[data-v-4551d3b2]{height:%?600?%;background-color:pink}',
"",
]);
是 内联css ,
而 可以 修改么? 可以 在 vue.config.js中 设置css.extract么?
不可以
查看代码, uni 是 使用 自定义 的 vue-cli-service 插件,
/node_modules/@dcloudio/vue-cli-plugin-uni/index.js
h5 强制要 内联css...
if (process.env.UNI_PLATFORM === 'h5' || process.env.UNI_USING_V3) {
options.css.extract = false
} else {
options.css.extract = true
}
height:%?600?%
在 cli 项目中, 根目录下会有postcss.config.js
实际上 使用了 uni的 一个自定义 插件require('@dcloudio/vue-cli-plugin-uni/packages/postcss')
在 parseWord方法中
if (process.env.UNI_PLATFORM === 'h5') {
if (u === 'upx' || u === 'rpx') {
// 这里 变成了很奇怪的东西
node.value = `%?${num}?%`
}
}
也就是 在编译的产物中, rpx/upx 都转成了 %?${num}?%的 格式
啥时候 转成 px 哦?
是 运行时!
运行时的 转换代码 是哪里来的?
是 通过 webpack的 loader 处理的
我写了一个 webpack 插件, 获取了 resolve 之后的 样式使用的loader
[
"/node_modules/@dcloudio/vue-cli-plugin-uni/packages/vue-loader/lib/loaders/pitcher.js",
"/node_modules/@dcloudio/vue-cli-plugin-uni/packages/h5-vue-style-loader/index.js",
"/node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js",
"/node_modules/@dcloudio/vue-cli-plugin-uni/packages/webpack-preprocess-loader/index.js",
"/node_modules/postcss-loader/dist/cjs.js",
"/node_modules/postcss-loader/dist/cjs.js",
"/node_modules/@dcloudio/vue-cli-plugin-uni/packages/sass-loader/dist/cjs.js",
"/node_modules/@dcloudio/vue-cli-plugin-uni/packages/webpack-preprocess-loader/index.js",
"/node_modules/@dcloudio/vue-cli-plugin-uni/packages/vue-loader/lib/index.js",
"/node_modules/@dcloudio/vue-cli-plugin-uni/packages/webpack-scoped-loader/index.js",
"/node_modules/@dcloudio/vue-cli-plugin-uni/packages/wrap-loader/index.js",
]
为什么会使用这个 h5-vue-style-loader?
用了 alias
在 /node_modules/@dcloudio/vue-cli-plugin-uni/lib/h5/index.js文件中配置了webpack
resolveLoader: {
alias: {
'vue-style-loader': resolve('packages/h5-vue-style-loader')
}
}
在 h5-vue-style-loader中 处理 css模块时,
编译源码是
var code = [
'// add the styles to the DOM',
'var add = require(' + addStylesClientPath + ').default',
'var update = add(' + id + ', content, ' + isProduction + ', ' + JSON.stringify(options) + ');'
]
动态 插入了 add/update 方法
执行后的返回示例:
// style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles
var content = require("........!../node_modules/@dcloudio/vue-cli-plugin-uni/packages/wrap-loader/index.js??clonedRuleSet-45[0].rules[0].use!./App.vue?vue&type=style&index=0&lang=scss&");
if(content.__esModule) content = content.default;
if(typeof content === 'string') content = [[module.id, content, '']];
if(content.locals) module.exports = content.locals;
// add the styles to the DOM
var add = require("!../node_modules/@dcloudio/vue-cli-plugin-uni/packages/h5-vue-style-loader/lib/addStylesClient.js").default
var update = add("43b7a677", content, true, {"sourceMap":false,"shadowMode":false});
也就是 这个 css 模块 变成了 上面的样子
运行时呢?
css模块 代码 注入了
var add = require("!../node_modules/@dcloudio/vue-cli-plugin-uni/packages/h5-vue-style-loader/lib/addStylesClient.js").default
源码是:
var UPX_RE = /%\?([+-]?\d+(\.\d+)?)\?%/g;
function processCss(css) {
var page = getPage();
if (typeof uni !== "undefined" && !uni.canIUse("css.var")) {
//不支持 css 变量
var offset = getWindowOffset();
css = css
.replace(VAR_STATUS_BAR_HEIGHT, "0px")
.replace(VAR_WINDOW_TOP, offset.top + "px")
.replace(VAR_WINDOW_BOTTOM, offset.bottom + "px")
.replace(VAR_WINDOW_LEFT, "0px")
.replace(VAR_WINDOW_RIGHT, "0px");
}
return css
.replace(BODY_SCOPED_RE, page)
.replace(BODY_RE, "")
.replace(PAGE_SCOPED_RE, "body." + page + " uni-page-body")
.replace(/\{[\s\S]+?\}|@media.+?\{/g, function (css) {
if (typeof uni === "undefined") {
return css;
}
// 这里 把 %?数值?% 格式的 数字样式 使用 upx2px 计算成px
return css.replace(UPX_RE, function (a, b) {
return uni.upx2px(b) + "px";
});
});
}
1 个评论
要回复文章请先登录或注册
r***@chn-das.com