uni-app 通过后缀名区分不同渠道版本

同一套微信小程序代码根据需求要打包成两款小程序,主要逻辑页面一致,主题色不一致,部分页面布局不,逻辑不一致。

script命令

先在package.json的script新增命令,根据不同的命令生成对应的环境变量,方便后续判断当前适用的版本。

pages.json配置

查询文档发现page.js可以定制pages.json的返回。所以在根目录新增page.js,
内容如下:

/**
如果要热部署,可以引用uni-pages-hot-modules
**/
try {
    var choofine = require(‘./config/version_a.js‘);
    var liftera = require(‘./config/version_b.js‘);
    module.exports = (pagesJson, loader) => {
        console.log(‘------------------当前开发版本为:‘+process.env.NODE_CF_ENV)
        if (process.env.NODE_CF_ENV == ‘version_a‘) {
            return version_a
        } else if (process.env.NODE_CF_ENV == ‘version_b‘) {
            return version_b
        }
    }

} catch (e) {
    console.log(e)
}

页面布局、代码逻辑

使用webpack loader在读取时判断读取文件, 比如有两个文件为:home.vue home.version_b.vue,在webpack执行时会根据环境变更输出不同的代码
loader配置:根目录新增 vue.config.js

module.exports = {
    chainWebpack: config => {
        // 访问到vue的规则配置,添加自己的loader相关逻辑,具体api自行参考https://github.com/neutrinojs/webpack-chain
        config.module
            .rule(‘vue‘)
            .use(‘./packages/platformSpecificLoader‘)
            .loader(‘./packages/platformSpecificLoader‘)
            .end();
        //如果不清楚最终的webpack配置,可以输出一下,根据自己的需求,通过api调整最终规则
        // console.log(config.toString());
    },
    configureWebpack: config =>{
        plugins: [
        ]
    }
}

loader代码

var fs = require("fs");
var nodePath = require("path");
var babelTemplate = require("@babel/template").default;

/**
如果import的组件有平台渠道对应的组件,则加载
**/
module.exports = function(babel) {
    return {
        name: "platformSpecificPlugin",
        visitor: {
            Program() {},
            ImportDeclaration: function importResolver(path, state) {
                const { opts: { pages } } = state;
                let fileName = path.node.source.value;
                if (pages.find(item => { return fileName.indexOf(item) != -1 })) {
                    const platformEnv = process.env.NODE_CF_ENV;
                    const transformedFileName = state.file.opts.filename;
                    const currentDir = nodePath.dirname(transformedFileName);
                    const ext = nodePath.extname(fileName);

                    var platformFileName = fileName.replace(ext, `.${platformEnv}${ext}`);
                    console.log(‘平台:‘ + platformEnv)
                    console.log(‘import文件:‘ + fileName)
                    console.log(‘当前文件:‘ + transformedFileName)
                    console.log(‘平台文件:‘ + platformFileName);
                    const fileExists = fs.existsSync(
                        nodePath.resolve(currentDir, platformFileName)
                    );
                    console.log(‘是否存在平台对应文件:‘ + fileExists);
                    if (fileExists) {
                        // path.node.source.value = platformFileName;
                        console.log(path.node)
                        const ast = astTernary(path,babel.types,platformFileName);
                        console.log(ast)
                        path.replaceWithMultiple(ast);

                        console.log(path.node)
                        return;
                    }
                }
            }
        }
    };
};

function astTernary(path,t,platformFileName) {
    // Omit the var assignment when specifier is empty (global import case, executing for the side-effects only).
    const newValue = `
import Page from ‘${platformFileName}‘;
`
    return babelTemplate.ast(newValue);
    // const newImports = path.node.specifiers.map( item => {
    //     return t.importDeclaration([t.importDefaultSpecifier(item.local)], t.stringLiteral(platformFileName))
    // });
    // return newImports
}

尝试过使用babel plugins进行不同版本代码文件的读取,发现输出的文件还是有问题。
TODO:这种情况下热加载有问题,在修改home.version_a.vue时未监听到变更,需要修改home.vue才监听到。

主题色

定义css变量,在vue文件中使用 var(--cf-theme)读取主题色。要实现不同的版本使用不同的主题色,可以使用uni-app的条件编译,具体参照官方文档。如果代码 逻辑差异不大的也可以使用条件编译而不使用上面的后缀名来区分版本

/*  #ifdef  MP-versiona*/
body {
  --cf-theme: #fd4373;
}
/*  #endif  */
/*  #ifdef  MP-versionb*/
body {
  --cf-theme: #85d7cf;
}
/*  #endif  */

uni-app 通过后缀名区分不同渠道版本

上一篇:解决windows 10 桌面右键时菜单显示出来需要很长时间的问题


下一篇:只能在手机浏览器中打开当前网址