浏览器直接加载 Vue单文件

543 阅读1分钟

What

简单来说,就是不想打包。 我寻思,vue单文件是天然微件,如果用SystemJS加载,在gitee上在线编辑后提交相当于直接部署生效。babel在线转译,IE11也可以直接用上async/await,可以玩一玩。

How

  • system的流程是:1.http获取字符串=》 2.babel到抽象语法树=》3.生成代码。
  • 我准备直接在2之前偷梁换柱
  • 以后再完成插件(多半没以后了,能用就行)

coding github (慢) gitee

优化的空间很大,可以玩很久


使用Vue3,好像不用纠结兼容IE了。boundless page preview

  1. asyncImportSFC
    async function asyncImportSFC(url) {
        if (VueComponents[url]) {
            return VueComponents[url];
        }
        const scfSourceCode = await loadText(url);
        const scfObjSourceCode = VueLoader(scfSourceCode);
        let scfObjAsyncFn = (...args) => {
            console.log(args);
        };
        try {
            scfObjAsyncFn = eval(scfObjSourceCode);
        } catch (e) {
            console.error(e);
        }
        const scfObj = await scfObjAsyncFn(window.Vue, {
            url
        });
        return scfObj;
    }

1.1 jQuery我的爱,用来加载原始的文本数据

function loadText(url) {
        return new Promise((resolve, reject) =>
            $.ajax({
                type: "GET",
                async: true,
                url,
                dataType: "text",
                success: resolve,
                error: reject
            })
        );
    };

1.2 文本分割,TEMPLATE_PLACEHOLDER用来占位,方便替换template

    function VueLoader(code) {
        function getSource(source, type) {
            var regex = new RegExp("<" + type + "[^>]*>");
            var openingTag = source.match(regex);
            if (!openingTag) return "";
            else openingTag = openingTag[0];
            var targetSource = source.slice(source.indexOf(openingTag) + openingTag.length, source.lastIndexOf("</" + type + ">"));
            return type === "template" ? targetSource.replace(/`/g, "\\`") : targetSource;
        }

        function splitCode() {
            if (!/TEMPLATE_PLACEHOLDER/.test(code)) {
                alert("SFC miss TEMPLATE_PLACEHOLDER");
                console.error(code);
            }
            return getSource(code, "script").replace(
                /TEMPLATE_PLACEHOLDER/,
                `template: \`${getSource(code, "template")}\``
            );
        }

        return splitCode();
    }