Front‑end Localized Deployment: DNS Forwarding and Asset Replacement Strategies
This article explains how a front‑end team can localize static resources for intranet deployment by either intercepting DNS requests to redirect CDN domains to internal servers or by scanning and replacing CDN URLs during the build process, and provides step‑by‑step implementation details with code examples.
Introduction
Modern front‑end teams often rely on an internal CI/CD platform to fetch code, install dependencies, build the project, upload static assets to a CDN, package the result into a container image, and finally deploy the image to Kubernetes. This article focuses on the static‑resource localization feature of such a platform.
Scenario Analysis
When a customer requires the entire application to run inside a secure intranet, we must ensure that no front‑end code accesses external resources. Typical external resources include CDN domains such as at.alicdn.com , internal CDNs like luban.zcycdn.com or sitecdn.zcycdn.com , and font files referenced in CSS.
<link rel='stylesheet' href='//at.alicdn.com/t/fontnm.css' />
<img src="https://sitecdn.zcycdn.com/f2e/8.png" alt="Recipient"/>
<img src="https://luban.zcycdn.com/f2e/8.png" alt="Recipient"/>
/* CSS font files */
src:url(https://sitecdn.zcycdn.com/t/font_148178j4i.eot);
src:url(https://sitecdn.zcycdn.com/t/font1_4i.woff);Two main solutions are considered:
Solution 1 – DNS Forwarding
DNS Resolution Forwarding
By configuring a local DNS server, we can intercept requests for CDN domains and resolve them to an internal IP address that serves the same static files. For example, a request to https://cdn.zcycdn.com/b/a.js can be redirected to https://demo.com/b/a.js without modifying the source code.
The approach avoids code changes but requires the customer to trust and maintain DNS rules and to handle HTTPS certificates, which must be renewed annually.
Implementation steps include starting a local static‑resource server, launching a DNS service that resolves the target domain to the server’s IP, configuring the DNS client, and testing both HTTP and HTTPS access.
Running a Local DNS Service
step1: Start a static‑resource service
Place the required static files in the service directory.
Verify that accessing http://juejin.cn:3000/zcy.png returns the local file http://10.201.45.121:3000/zcy.png .
step2: Launch the DNS server
step3: Configure local DNS resolution
step4: Test HTTP and HTTPS access
HTTP request succeeds, while HTTPS fails due to missing valid certificates, illustrating the need for proper TLS handling.
HTTPS requires a valid certificate and a TLS handshake, which DNS alone cannot provide.
Solution 2 – Build‑time Asset Replacement
During the build, the pipeline scans for CDN URLs, downloads the assets to the customer’s server, and rewrites the source files to point to the local addresses. This approach requires no client‑side DNS changes but modifies the code.
Four‑stage Implementation
1. Unified runCommand helper
function runCommand(cmd, args, options, before, end) {
log(before, blue);
const spawn = childProcess.spawn(
cmd,
args,
Object.assign({ cwd: global.WORKSPACE, stdio: 'inherit', shell: true }, options)
);
spawn.on('error', (error) => { log(error, chalk.red); reject(error); });
spawn.on('close', (code) => {
if (code !== 0) { return reject(`sh: ${cmd} ${args.join(' ')}`); }
end && log(end, green);
resolve();
});
}2. Pre‑check and environment preparation
Switch npm registry, install dependencies, etc.
runCommand('nrm', ['use', 'zcy-server'], {}, 'switch nrm registry to zcy', 'switch nrm registry to zcy success');
runCommand('npm', ['i', '--unsafe-perm'], {}, 'npm install', 'npm install success');3. Compile and adjust publicPath
const cdnConfigStr = `assetsPublicPath: 'http://dev.com',`;
replaceFileContent(configPath, /assetsPublicPath:.+,/, cdnConfigStr);4. Static‑resource replacement
Download identified assets, rewrite URLs in the build output, and finally push the assets to an OSS bucket.
const downloadAssetsFiles = async (img, folder) => {
const staticAssets = 'staticAssets';
const assetsUrl = getPwdPath(`${folder || ''}${path.sep}${staticAssets}`);
if (!fs.existsSync(assetsUrl)) { fs.mkdirSync(assetsUrl); }
return Promise.all(img.objUnique('src').map(({ src, fileName }) => {
if (!fileName) return;
return new Promise((resolve, reject) => {
const originFileDir = path.join(assetsUrl, path.dirname(url.parse(src).pathname));
fs.mkdirSync(originFileDir, { recursive: true });
const uri = path.join(originFileDir, fileName);
download(uri, src, resolve, reject);
});
}));
};5. Push to OSS
const ossEndpoint = process.env.OSS_ENDPOINT;
const commonOptions = {
accessKeyId: process.env.OSS_ACCESSKEYID,
accessKeySecret: process.env.OSS_ACCESSKEYSECRET,
bucket: process.env.OSS_BUCKET,
timeout: '120s',
};
const extraOptions = ossEndpoint ? { endpoint: ossEndpoint, cname: true } : { region: process.env.OSS_REGION };
const ossOptions = Object.assign({}, commonOptions, extraOptions);
const client = new OSS(ossOptions);
result = await client.put(onlinePath, curPath);References include SSL/TLS certificate validity rules, Node.js child_process documentation, and deep dives into Node.js processes and threads.
政采云技术
ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.