ts 编译运行时,为何没有正确加载 JavaScript 文件?

报错如下:

Failed to load resource: the server responded with a status of 404 (Not Found) http://…ake_game/bin/game

我是通过执行npx tsc,编译 Typescript 生成的 JavaScript 脚本。

我自己排查过,是因为加载的文件没有后缀,正确的加载应该是 game.js ,我只要修改 main.js 就可以了,import { *Game* } from './game';改成import { *Game* } from './game.js';可是 main.js 是 main.ts 生成的。请问这个有什么解决方法?

我尝试过Chatgpt,它提示让我输出一个文件,但是这不是我想要的解决方案。

项目目录结构如下:

│  index.html
│  package-lock.json
│  package.json
│  tsconfig.json
├─bin
│      game.js
│      game.js.mapmain.jsmain.js.map
│      snake.js
│      snake.js.map
│      
└─src
        game.ts
        main.ts
        snake.ts

index.html

<script src="./bin/main.js" type="module"></script>

main.ts

import { Game } from './game';

const game = new Game();
game.start();

game.ts

export class Game {
}

tsconfig.json

{
    "compilerOptions": {
        "target": "es5",
        "module": "es2015",
        "moduleResolution": "node",
        "strict": true,
        "esModuleInterop": true,
        "sourceMap": true,
        "outDir": "./bin"
    },
    "include": [
        "src/**/*.ts"
    ],
    "exclude": [
        "node_modules"
    ]
}

问题产生的原因:
https://github.com/microsoft/TypeScript/issues/16577
情况可以考虑自己对编译后的文件二次处理,或者在你的服务器上做 rewrite。

我是通过服务器rewrite解决,nginx配置如下所示:

server {
        listen       80;

        #   指定允许跨域的方法,*代表所有
        add_header Access-Control-Allow-Methods *;
    
        #   预检命令的缓存,如果不缓存每次会发送两次请求
        add_header Access-Control-Max-Age 3600;
        #   带cookie请求需要加上这个字段,并设置为true
        add_header Access-Control-Allow-Credentials true;
    
        #   表示允许这个域跨域调用(客户端发送请求的域名和端口) 
        #   $http_origin动态获取请求客户端请求的域   不用*的原因是带cookie的请求不支持*号
        add_header Access-Control-Allow-Origin $http_origin;
    
        #   表示请求头的字段 动态获取
        add_header Access-Control-Allow-Headers 
        $http_access_control_request_headers;
    
        #   OPTIONS预检命令,预检命令通过时才发送请求
        #   检查请求的类型是不是预检命令
        if ($request_method = OPTIONS){
            return 200;
        }
    
        location / {
            root   C:/Users/Intel/Desktop/snake_game;
            index  index.html index.htm;
            
            # 处理 /bin 目录下的请求
            location /bin/ {
                # 如果请求的路径具有任意后缀名文件,则不进行重写
                location ~* \..+$ {
                    #   指定允许跨域的方法,*代表所有
                    add_header Access-Control-Allow-Methods *;
    
                    #   预检命令的缓存,如果不缓存每次会发送两次请求
                    add_header Access-Control-Max-Age 3600;
                    #   带cookie请求需要加上这个字段,并设置为true
                    add_header Access-Control-Allow-Credentials true;
    
                    #   表示允许这个域跨域调用(客户端发送请求的域名和端口) 
                    #   $http_origin动态获取请求客户端请求的域   不用*的原因是带cookie的请求不支持*号
                    add_header Access-Control-Allow-Origin $http_origin;
    
                    #   表示请求头的字段 动态获取
                    add_header Access-Control-Allow-Headers 
                    $http_access_control_request_headers;
    
                    #   OPTIONS预检命令,预检命令通过时才发送请求
                    #   检查请求的类型是不是预检命令
                    if ($request_method = OPTIONS){
                        return 200;
                    }
    
                    break;
                }
    
                # 如果请求的文件不带后缀名,则增加js,则进行重写
                rewrite ^/bin/(.*)$ /bin/$1.js break;
    
                # 如果请求的是不存在的文件,则返回 404 错误
                try_files $uri =404;
            }
        }
    }
    # 关闭后台执行
    daemon off;