如何在没有捆绑的情况下将为AMD编写的代码重写/重新打包到CommonJs?

问题描述 投票:1回答:1

我有一个使用AMD模块为浏览器编写的项目,现在我需要在nodejs中运行相同的代码,所以我需要将每个文件重写为使用CommonJs模块。我试过webpack,但它给了我一个我不需要的包。我想要的只是保存我的文件,但重写define(..导入到require(..)

javascript node.js webpack amd commonjs
1个回答
1
投票

感谢Felix Kling的建议,我在打字稿中写了下面的变换器

import { FileInfo, API, Options } from 'jscodeshift';
import { resolve, normalize, relative } from 'path';

export default function transformer(file: FileInfo, api: API, options: Options) {
    const { j } = api;
    return j(file.source)
        .find(j.ExpressionStatement, { expression: { callee: { name: 'define' } } })
        .replaceWith(({ node }) => {
            const { expression: defineCallExpression } = node;

            if (defineCallExpression.type !== 'CallExpression') return crash('No call to define function of AMD.');
            const [moduleLocationsArray, callback] = defineCallExpression.arguments;
            if (callback.type !== 'FunctionExpression') return;
            if (moduleLocationsArray.type !== 'ArrayExpression') return;

            const imports = moduleLocationsArray.elements.map((element, index) => {
                if (element === null) return crash('Module name skipped.');
                if (element.type !== 'Literal') return crash('Module name is not a literal');
                const param = callback.params[index];
                if (param.type !== 'Identifier') return crash('Module parameter is not an identifier.');
                return {
                    location: element.value as string,
                    name: param.name,
                };
            }).filter(pair => shouldKeepModule(pair.location));

            const filePath = normalize(resolve(__dirname, file.path));
            const baseDir = normalize(resolve(__dirname, options.where));
            const importStatements = imports.map(({name, location}) => {
                const modulePath = normalize(resolve(baseDir, location));
                const relativeModuleName = slashings(relative(filePath, modulePath));
                const text = `const ${name} = require('${relativeModuleName}');`;
                const statement = api.j(text, options);
                return statement;
            });
            const statementsBefore = callback.body.body;
            const statementsAfter = [...importStatements, ...statementsBefore];
            return statementsAfter;
        })
        .toSource();
}

function shouldKeepModule(location: string): boolean {
    return location !== 'module' && location !== 'exports' && location !== 'require';
}
function crash(message: string): never { throw new Error(message); }
function slashings(text: string): string { return text.replace(/\\/g, '/'); }

以下tsconfig.json

{
    "compileOnSave": true,
    "compilerOptions": {
        "strict": true,
        "target": "es6",
        "module": "commonjs",
        "lib": ["es6"],
        "types": ["node", "jscodeshift"],
        "outDir": "../../node_modules/amd-to-commonjs"
    }
}

以下package.json

{
    "private": true,
    "devDependencies": {
        "@types/node": "7.0.4",
        "@types/jscodeshift": "0.6.0",
        "jscodeshift": "0.6.3",
        "typescript": "3.4.0-dev.20190227"
    }
}

由以下命令构建

npm install
node ../../node_modules/typescript/bin/tsc --project ./

并通过以下命令运行

node ../../node_modules/jscodeshift/bin/jscodeshift.js --transform=../../node_modules/amd-to-commonjs/transformer.js --where=../../scripts/built ../../scripts/built
© www.soinside.com 2019 - 2024. All rights reserved.