Bulk-Replacing Domains in a Frontend Codebase

· 2 min read · 652 Words · -Views -Comments

We ship both CN and international sites from one codebase. Historically we hardcoded CN links and let a 302 redirect to the international domain. That redirect was disabled, so we needed to replace scattered hardcoded domains with a dynamic variable, e.g., https://1991421.cn/...https://${window.basicHost}/.... How to do this cleanly?

Plain regex search/replace?

首先,想到的是直接的正则替换,但是尝试了下发现并不行,原因是ES6加下的代码写法种类太多,且这个问题根本上来说是将常量改成了变量拼接,因此直接文本替换是不行的。

Examples: link strings appear in various contexts

href="https://1991421.cn/2021/09/21/844e39cc/"

href="//1991421.cn/2021/09/21/844e39cc/"

href={`//1991421.cn/2021/09/21/${postId}`}

getUrl(`//1991421.cn/2021/09/21/${postId}`)

AST + regex replacement

直接正则替换无法解决的直接原因是写法的不同,但是如果在代码编译到ES5后,写法即固定了,一定是单独的字符串,比如"//1991421.cn/2021/09/21/"+ postId。而这个时间点可以在webpack中很容易找到找到,比如compilation.hooks.optimizeChunkAssets

At this stage regex can replace strings, but you also need to handle surrounding quotes and build concatenations with variables. Pure regex gets messy; AST makes it straightforward by analyzing JS syntax and locating string literals properly. This leads to writing a webpack plugin.

Implementation

Webpack plugin

因为最终是将JS代码进行解析转为AST,从而正则替换部分字符串,因此webpack插件来做最为合适。

具体插件可以在这里下载使用

  1. webpack插件部分,根据webpack暴露的hook选择chunk生成后的hook即可。
  2. 获取chunk源码,做AST解析从而实现替换即可。

Core replacement logic:


function replaceDomainLoader(source) {
  const tokenization = esprima.tokenize(source);
  tokenization.forEach((item) => {
    if (item.type !== 'String') return;
    const mark = item.value.charAt(0); // 获取字符串的标签
    const {value} = item;
    let res = value;
    replaceQueue.forEach((obj) => {
      res = res.replace(obj.reg, `${mark} + ${obj.value} + ${mark}`); 
    });
    if (value === res) return;
    source = source.replace(value, res);
  });
  return source;
}

HMR caveat

当前如果是开发模式- HMR下会出现替换错误,因此建议插件增加环境判定,比如

...
process.env.NODE_ENV === 'production' && new DomainReplacePlugin()
...

For local production builds, set env vars reliably, e.g., with cross‑env:

npx cross-env NODE_ENV=production npm run build:dev

Final Thoughts

This approach keeps business code clean while making domain handling flexible across CN/intl sites.

参考文档

Authors
Developer, digital product enthusiast, tinkerer, sharer, open source lover