如何在附加“.ts”扩展名之前告诉 webpack 删除“.js”?

时间:2021-07-04 16:55:19

标签: javascript webpack es6-modules

我在这样的项目中有导入:

import { ytheme } from "./ytheme.js";

为什么?因为: https://www.typescriptlang.org/docs/handbook/2/modules.html#es-module-syntaxAppending .js extension on relative import statements during Typescript compilation (ES6 modules)(第一个答案)

Webpack 尝试通过错误来解决它:

 Field 'browser' doesn't contain a valid alias configuration
        <...>\src\client\components\ytheme.js.ts doesn't exist

这显然行不通。正确的路径应该是:

<...>\src\client\components\ytheme.ts

问题:在解析导入时,如何配置 webpack 以在附加“.ts”之前删除“.js”?

========== 详情==========

webpack.config.js

const path = require("path");
const fs = require("fs");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin").CleanWebpackPlugin;
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
const isDevelopment = process.env.NODE_ENV !== "production";

const pathes = (() => {
    const proj = path.resolve(__dirname);
    const projParts = proj.split(path.sep);
    const projName = projParts[projParts.length - 1];
    const root = path.resolve(__dirname, "");

    return {
        root,
        proj,
        projName,
        resources: path.resolve(proj, "resources"),
        bundles: path.resolve(proj, "lib/bundles", projName),
    };
})();

for (let k in pathes) console.log(`pathes.${k} = ${pathes[k]}`);

const NODE_ENV = "development";

let BUILD_DATE = new Date();
BUILD_DATE.setTime(BUILD_DATE.getTime() + 3 * 60 * 60 * 1000);
BUILD_DATE = JSON.stringify(BUILD_DATE);
BUILD_DATE = BUILD_DATE.substr(1, 10) + " " + BUILD_DATE.substr(12, 8);

console.log("");
console.log("BUILD_DATE = " + BUILD_DATE);
console.log("");

let package_json;
let manifest_json;

package_json = JSON.parse(fs.readFileSync(path.resolve(pathes.root, "package.json"), { encoding: "utf-8" }));
manifest_json = JSON.parse(fs.readFileSync(path.resolve(pathes.resources, "manifest.json"), { encoding: "utf-8" }));
let tsconf = eval("(()=>(" + fs.readFileSync("tsconfig.json", "utf-8") + "))()");

let moduleAliases = {};
for (let k in tsconf.compilerOptions.paths) {
    let v = tsconf.compilerOptions.paths[k];
    moduleAliases[k] = path.resolve(pathes.root, "ts_out", v[0]);
}

let excludedModules = [
    "fs",
    "sql-prettier",
    "prettier",
    "express",
    "socket.io",
    "better-sqlite3",
    "sqlite3",
    "child_process",
];

module.exports = {
    // TODO REMOVED ON 2020-13-11
    // node: {
    //     fs: "empty",
    //     child_process: "empty",
    // },
    mode: "development",
    entry: [path.resolve(pathes.proj, "src/client/indexSmall.tsx")],
    devtool: "inline-source-map",
    devServer: {
        contentBase: "./resources",
        hot: true,
    },
    resolve: {
        fallback: {
            crypto: false,
            fs: false,
            child_process: false,
            path: false,
            constants: false,
            util: false,
            assert: false,
            stream: false,
            //            crypto: require.resolve("crypto-browserify"),
            //            fs:null,
        },
        //        root:               path.join(pathes.proj, 'js'),
        //        modulesDirectories: ['node_modules'],
        extensions: ["", ".ts", ".tsx", ".js", ".jsx", ".json"],
        alias: {
            "react-dom": "@hot-loader/react-dom",
            ...moduleAliases,
        },
    },
    output: {
        path: pathes.bundles,
        filename: "bundle.js",
    },
    module: {
        rules: [
            {
                test: (modulePath0) => {
                    let modulePath = modulePath0.split(path.sep);
                    for (let excludedModule of excludedModules) if (modulePath.includes(excludedModule)) return true;
                    return false;
                },
                use: "null-loader",
            },
            {
                test: /\.css$/,
                use: [
                    "style-loader", // creates style nodes from JS strings
                    "css-loader", // translates CSS into CommonJS
                ],
            },
            {
                test: /\.scss$/,
                use: [
                    "style-loader", // creates style nodes from JS strings
                    "css-loader", // translates CSS into CommonJS
                    "sass-loader", // compiles Sass to CSS, using Node Sass by default
                ],
            },
            {
                test: /\.(j|t)sx?$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader",
                    options: {
                        cacheDirectory: true,
                        babelrc: false,
                        presets: ["@babel/preset-typescript", "@babel/preset-react"],
                        plugins: [
                            ["@babel/plugin-proposal-decorators", { legacy: true }],
                            "@babel/proposal-optional-chaining",
                            ["@babel/proposal-class-properties", { legacy: true }],
                            "@babel/proposal-object-rest-spread",
                            //                            "react-hot-loader/babel",
                            [
                                "module-resolver",
                                {
                                    root: ["./"],
                                    alias: moduleAliases,
                                },
                            ],
                            // "@babel/transform-modules-commonjs",
                        ],
                    },
                },
            },
        ],
    },
    plugins: [
        new webpack.DefinePlugin({
            BROWSER: "true",
            "process.env.BROWSER": "true",
            NODE_ENV: JSON.stringify(NODE_ENV),
            BUILD_DATE: JSON.stringify(BUILD_DATE),
            //             BASE_URL:JSON.stringify(private_js ? private_js.url : 'http://localhost')
        }),
        new CleanWebpackPlugin(),
        //        new webpack.NamedModulesPlugin(), // TODO REMOVED ON 2020-13-11
        new HtmlWebpackPlugin({ title: manifest_json.name }),
        isDevelopment && new webpack.HotModuleReplacementPlugin(),
        isDevelopment && new ReactRefreshWebpackPlugin(),
    ],
    //  watchOptions : {
    //      aggregateTimeout : 300
    //  },
    // "cheap-inline-module-source-map"
};

// console.log('YYAWEBPACK', JSON.stringify(module.exports.resolve.alias,null, "\t"));

我运行开发服务器的命令

webpack-cli serve --mode development --config webpack.frontend.config.js

完全错误

ERROR in ./src/client/indexSmall.tsx 7:0-48
Module not found: Error: Can't resolve './components/ytheme.js' in 'D:\b\Mine\GIT_Work\yatasks_one_api\src\client'
resolve './components/ytheme.js' in 'D:\b\Mine\GIT_Work\yatasks_one_api\src\client'
  using description file: D:\b\Mine\GIT_Work\yatasks_one_api\package.json (relative path: ./src/client)
    Field 'browser' doesn't contain a valid alias configuration
    using description file: D:\b\Mine\GIT_Work\yatasks_one_api\package.json (relative path: ./src/client/components/ytheme.js)
      Field 'browser' doesn't contain a valid alias configuration
      D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js doesn't exist
      .ts
        Field 'browser' doesn't contain a valid alias configuration
        D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js.ts doesn't exist
      .tsx
        Field 'browser' doesn't contain a valid alias configuration
        D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js.tsx doesn't exist
      .js
        Field 'browser' doesn't contain a valid alias configuration
        D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js.js doesn't exist
      .jsx
        Field 'browser' doesn't contain a valid alias configuration
        D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js.jsx doesn't exist
      .json
        Field 'browser' doesn't contain a valid alias configuration
        D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js.json doesn't exist
      as directory
        D:\b\Mine\GIT_Work\yatasks_one_api\src\client\components\ytheme.js doesn't exist

webpack 5.41.1 compiled with 2 errors in 2120 ms
i 「wdm」: Failed to compile.

1 个答案:

答案 0 :(得分:0)

作为一种解决方法,以下代码段似乎有效:

{ // webpack.config.cjs
    plugins: [
        new webpack.NormalModuleReplacementPlugin(/.*/, function (resource) {
            const lowerCaseRequest = resource.request.toLowerCase();

            if (
                !lowerCaseRequest.includes("node_modules") &&
                lowerCaseRequest.endsWith(".js") &&
                lowerCaseRequest[0] === "." &&
                resource.context.startsWith(path.resolve(__dirname))&&
                !resource.context.toLowerCase().includes("node_modules")
            ) {
                resource.request = resource.request.substr(0, resource.request.length - 3) + ".ts";
resource.request });
            }
        }),
        ...]
}