手写自己的编译模板loader

185 阅读1分钟

创建loader

  1. 创建package.json
  • npm init -y
  1. 生产环境安装webpack三大件
    "devDependencies": {
        "webpack": "^4.30.0",
        "webpack-cli": "^3.3.0",
        "webpack-dev-server": "^3.7.2"
    }
  • npm i
  1. 新建webpack.config.js
    // commonjs 与 ES6
    // module.exports require 与 export import

    const { resolve } = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");

    module.exports = {
        mode: "development",
        entry: resolve(__dirname, "src/app.js"),
        output: {
            path: resolve(__dirname, "dist"),
            // filename: "[name].[hash:8].js"
            filename: "app.js"
        },
        devtool: "source-map",
        module: {
            rules: [
                {
                    test: /\.tpl$/,
                    use: [
                        "babel-loader",
                        {
                            // 可以直接写自己创建的loader绝对路径 或者resolveLoader配置,就可以直接使用loader名称使用
                            // loader: resolve(__dirname, "loaders", "tpl-loader"),
                            loader: "tpl-loader",
                            options: {
                                log: true
                            }
                        }
                    ]
                }
            ]
        },
        plugins: [
            new HtmlWebpackPlugin({
                template: resolve(__dirname, "index.html")
            })
        ],
        devServer: {
            port: 3333,
            open: true
        },
        resolveLoader: {
            // 使用loader 先去node_modules找 找不到再去loaders里找
            modules: ["./node_modules", "./loaders"]
        }
    }
  1. 安装babel
  • npm install -D babel-loader @babel/core html-webpack-plugin
  1. 新建src/app.js、info.tpl loaders/utils、tpl-loader/index.js 等文件
    // src/app.js
    
    import tpl from "./info.tpl";
    const oApp = document.querySelector("#app");
    const info = {
        name: "迪奥",
        age: "1岁"
    }

    oApp.innerHTML = tpl(info);
    // src/info.tpl
    
    <div>
        <h1>{{ name }}</h1>
        <h1>{{ age }}</h1>
    </div>
    // loaders/utils.js
    
    function tplReplace (template, replaceObj) {
        // 取{{}} 中的字段替换为值
        return template.replace(/\{\{(.*?)\}\}/g, function (node, key) {
            return replaceObj[key];
        });
    }

    module.exports = {
        tplReplace
    }
    // loaders/tpl-loader/index.js
    
    const { getOptions } = require("loader-utils");
    const { tplReplace } = require("../utils");

    function tplLoader (source) {
        /**
        * .tpl文件 防止出错去掉空格
        */
        source = source.replace(/\s+/g, "");
        console.log(source);

        // 获取配置的options,两种方式
        const { log } = getOptions(this);
        console.log(log);
        console.log(this.query.log);

        const _log = log ? ```console.log("compiled the file which is from ${ this.resourcePath }")``` : "";

        // return的options入参就是app.js中传入的info
        return ```
            export default (options) => {
                ${ tplReplace.toString() }
                ${ _log.toString() }
                return tplReplace('${source}', options)
            }
        ```
    }

    module.exports = tplLoader;
  1. 修改package.json scripts
    "scripts": {
        "dev": "webpack-dev-server"
    },