最近的前端代码越写越回去了,因为加入的新公司有一些很老的设备,用的node0.10这种老古董,需要兼容其代码。
虽然是可以写新语法,让Babel之类的去转,但是......Set、AbortSignal之类的新语法它也是不会自动转的,估计还得新增polyfill去搞。算了,在未完全懂清这套老代码的规则下删除和替换吧。
然后是pixijs这个库,里面的语法太新了,什么"??"、".?"都是识别不了的,经过处理后还有"globalThis is not defined"的报错,这个处理完还有for循环在"旧环境里 for...in 把数组原型链上的可枚举属性也枚举出来了"导致的"t is not a constructor"的报错。
在webpack.config.js加fix-vendor.js二次处理后确实处理成功了:
javascript
// webpack.config.js片段
{
test: /\.js$/,
include: /node_modules\/pixi\.js/,
use: {
loader: 'esbuild-loader',
options: {
target: 'es2015',
},
},
}
// fix-vendor.js
const fs = require('fs');
const path = require('path');
const babel = require('@babel/core');
const distDir = path.resolve(__dirname, 'dist');
if (!fs.existsSync(distDir)) {
console.log('未找到 dist 目录,无需处理');
process.exit(0);
}
const files = fs.readdirSync(distDir).filter((file) => file.endsWith('.js'));
if (files.length === 0) {
console.log('未找到 dist 目录下的 .js 文件,无需处理');
process.exit(0);
}
const targets = {
chrome: '49',
firefox: '52',
safari: '10',
edge: '14',
};
const presetEnv = [
'@babel/preset-env',
{
targets,
modules: false,
bugfixes: true,
shippedProposals: false,
useBuiltIns: false,
},
];
const globalThisPolyfill = `(function(){
if(typeof globalThis==="object")return;
Object.defineProperty(Object.prototype,"__global_this__",{
get:function(){return this},
configurable:true
});
__global_this__.globalThis=__global_this__;
delete Object.prototype.__global_this__;
})();`;
files.forEach((file) => {
const filePath = path.join(distDir, file);
const source = fs.readFileSync(filePath, 'utf-8');
const result = babel.transformSync(source, {
presets: [presetEnv],
sourceType: 'unambiguous',
compact: true,
minified: true,
filename: filePath,
});
if (!result || typeof result.code !== 'string') {
console.error(`转换 ${file} 失败`);
process.exit(1);
}
let code = result.code;
if (!/globalThis/.test(code)) {
code = `${globalThisPolyfill}\n${code}`;
} else {
code = `${globalThisPolyfill}\n${code}`;
}
fs.writeFileSync(filePath, code, 'utf-8');
});
console.log('已完成 dist 下 .js 文件的兼容性转换。');
但是双重处理太麻烦了,于是把fix-vendor.js删掉,只保留webpack.config.js,并在main.ts里加兼容处理:
TypeScript
// webpack.config.js 片段
{
test: /\.m?js$/,
include: [
path.resolve(__dirname, 'node_modules/pixi.js'),
path.resolve(__dirname, 'node_modules/@pixi'),
],
use: {
loader: 'esbuild-loader',
options: {
target: 'es2015',
},
},
},
// main.ts 增加片段
// 兼容性修复
const arrayProto: any = Array.prototype;
if (typeof arrayProto['at'] === 'function') {
const atFn = arrayProto['at'];
delete arrayProto['at'];
Object.defineProperty(arrayProto, 'at', {
value: atFn,
configurable: true,
writable: true,
enumerable: false,
});
}
// 兼容globalThis,确保在各种环境下都能访问到全局对象
if (typeof globalThis === 'undefined') {
Object.defineProperty(Object.prototype, '__global_this__', {
get() {
return this;
},
configurable: true,
});
// @ts-ignore
__global_this__.globalThis = __global_this__;
// @ts-ignore
delete Object.prototype.__global_this__;
}