04月10, 2017

create-react-app自定义脚本

在使用create-react-app的时候,会各种不如意。

比如:

  • 不支持antd
  • 不支持less

我们的做法通常会采用npm run eject,然后让configs文件到本地来做修改、调整。

一个项目这样做没问题,但多个项目,又要这样折腾一下,确实心累。

于是我的伙计让我想办法搞一个脚手架出来。一开始的思路,是将eject后的成果,丢到一个项目里面,然后用一个全局的npm命令,下载下来并执行npm。

但后面想想,这样似乎没啥意思。然后先看一下create-react-app的实现吧。

从代码的实现来看,它的模板是放在react-scripts的npm包里面。

但其实这个react-scripts是可以修改的。我们运行create-react-app --help

react-scripts

来看一下它的实现吧:


const packageToInstall = getInstallPackage(version); // 这个version是scriptsVersion

function getInstallPackage(version) {
    let packageToInstall = "react-scripts"; // 默认的npm包为react-scripts
    const validSemver = semver.valid(version);
    if (validSemver) {
        packageToInstall += `@${validSemver}`;
    } else if (version) {
        // for tar.gz or alternative paths
        packageToInstall = version;
    }
    return packageToInstall;
}

所以我们完全可以fork一版react-scripts出来,然后根据自己的需求,改造出来一份自定义的custom-react-scripts。

于是下午就搞了一个出来:支持less及antd的react-scripts。暂时不支持装饰器,后面会将它加上。

细看create-react-app.js,发现有些实现还相当不错,譬如代码考虑到了用npm还是用yarn。

判断用户电脑有没有装yarn:

function shouldUseYarn() {
    try {
        execSync("yarnpkg --version", { stdio: "ignore" });
        return true;
    } catch (e) {
        return false;
    }
}

安装npm的实现(用到了cross-spawn):

function install(useYarn, dependencies, verbose, isOnline) {
    return new Promise((resolve, reject) => {
        let command;
        let args;
        if (useYarn) {
            command = "yarnpkg";
            args = ["add", "--exact"];
            if (!isOnline) {
                args.push("--offline");
            }
            [].push.apply(args, dependencies);

            if (!isOnline) {
                console.log(chalk.yellow("You appear to be offline."));
                console.log(chalk.yellow("Falling back to the local Yarn cache."));
                console.log();
            }
        } else {
            checkNpmVersion();
            command = "npm";
            args = ["install", "--save", "--save-exact"].concat(dependencies);
        }

        if (verbose) {
            args.push("--verbose");
        }

        const child = spawn(command, args, { stdio: "inherit" });
        child.on("close", code => {
            if (code !== 0) {
                reject({
                    command: `${command} ${args.join(" ")}`,
                });
                return;
            }
            resolve();
        });
    });
}

本文链接:www.my-fe.pub/post/create-react-app-custom-scripts.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。