• 技术文章 >微信小程序 >小程序开发

    微信小程序转换器之 loader设计实现

    coldplay.xixicoldplay.xixi2020-11-19 17:36:12转载345

    小程序开发教程栏目介绍loader设计实现。

    配置文件中的loader配置

    可以根据配置文件匹配到到规则,去执行相应的loader。

    // analyze.config.js
    // 引入loader
    const jsLoader = require('./lib/jsLoader')
    const jsonLoader = require('./lib/jsonLoader')
    const cssLoader = require('./lib/cssLoader')
    const htmlLoader = require('./lib/htmlLoader')
    const signLoader = require('./lib/signLoader')
    const config = {
        entry: './',
        output: {
            name: 'dist',
            src: './'
        },
        module: [
            {
                test: /\.js$/,
                loader: [signLoader, jsLoader],
            },
            {
                test: /\.wxss$/,
                loader: [cssLoader],
                outputPath: (outputPath) => outputPath.replace('.wxss', '.acss')
            },
            {
                test: /\.wxml$/,
                loader: [htmlLoader],
                outputPath: (outputPath) => outputPath.replace('.wxml', '.axml')
            },
            {
                test: /\.json$/,
                loader: [jsonLoader],
            },
        ]
    }
    module.exports = config

    具体loader实现
    以jsLoader为例子,接收源码作为参数,返回编译后获得的新的源码

    // 前几篇中封装的js转换器
    const JsParser = require('./JsParser')
    function loader(source) {
        
        const jsParser = new JsParser()
        let ast = jsParser.parse(source)
        ast = jsParser.astConverter(ast)
        return jsParser.astToCode(ast)
    }
    module.exports = loader

    不同文件选择对应loader

    // 重写Analyze函数中的analyzeFileToLoard文件分析部分
    function Analyze(filePath, outputPath){
        if (fs.statSync(filePath).isDirectory()) {
            const files = fs.readdirSync(filePath)
            files.forEach(file => {
                const currentFilePath = filePath+'/'+file
                const currentOutputPath = outputPath+'/'+file
                if(fs.statSync(currentFilePath).isDirectory()) {
                    fs.mkdirSync(currentOutputPath)
                    Analyze(currentFilePath, currentOutputPath)
                } else analyzeFileToLoard(currentFilePath, currentOutputPath)
            })
        } else analyzeFileToLoard(filePath, outputPath)
    }
    function analyzeFileToLoard(inputPath, outputPath) {
        let source = readFile(inputPath) // 读取源码
        const loaders = config.module
        loaders.forEach(loader => { // 遍历配置文件,看是否有匹配文件的loader规则
            if (loader.test.test(inputPath)) {
                // 使用loader
                source = useLoader(source, loader.loader, outputPath)
                // 输出路径处理函数
                if (loader.outputPath) outputPath = loader.outputPath(outputPath)
            }
        })
        writeFile(outputAppPath(outputPath), source) // 将处理过后的源码写入文件
    }

    loader过滤和执行

    loader执行是个逆序的执行,从右边向左依次执行。在这里我们先用同步的loader来做讨论。
    loader执行前还有个pitch阶段,感觉pitch这个起名方式并不是特别合适,我更愿意叫它过滤筛选阶段。先去顺序执行loader上的pitch方法,要是pitch有返回值,就不再执行在该loader之前执行的loader。

    function useLoader(source, loaders = []) {
        // 执行loader存储列表
        const loaderList = []
        // 递归去筛选需要执行的loader
        function loaderFilter(loaders) {
            const [firstLoader, ...ortherLoader] = loaders
            if (loaders.length === 0) return
            // 执行pitch,并将剩余的loader传入作为参数
            if (firstLoader.pitch && firstLoader.pitch(ortherLoader)) return ortherLoader
            else {
                // 将可用loader加入待执行列表
                loaderList.push(firstLoader)
                // 剩余loader作为参数 递归调用
                loaderFilter(ortherLoader)
            }
        }
        // 大概,暂时用不到。。。
        const remainLoader = loaderFilter(loaders)
        // 同步loader逆序执行
        function runLoader(source, loaderList) {
            const loader = loaderList.pop()
            let newSource = loader(source)
            if (loaderList.length > 0) return runLoader(newSource, loaderList)
            else return newSource
        }
        source = runLoader(source, loaderList)
        return source
    }

    实验
    写个signLoader,看看loader能不能像我们想的那样逆序执行

    function loader(source) {
    let sign = `/**
    * @Author: LY
    */
    `
        source = sign + source
        return source
    }
    module.exports = loader

    结果:

    这样简易的loader部分算是完成了,但这么写只能执行一些同步的loader,异步的loader无法等待执行完成后再写入。

    bfd26c39c430cd836b42d9db78aa336.png

    相关学习推荐:小程序开发教程

    以上就是微信小程序转换器之 loader设计实现的详细内容,更多请关注php中文网其它相关文章!

    本文转载于:juejin,如有侵犯,请联系a@php.cn删除
    上一篇:使用矢量字体自定义小程序 icon 组件图标 下一篇:介绍微信小程序 canvas开发的注意事项
    第14期线上培训班

    相关文章推荐

    • 如何使用纯CSS实现菱形loader效果(附源码)• Webpack如何实现Loader?(附代码)• 简单实用的进度条加载组件loader.js• ThinkPHP自动加载Loader源码解析

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网