V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
z888888cn
V2EX  ›  TypeScript

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

  •  
  •   z888888cn · 353 天前 · 1279 次点击
    这是一个创建于 353 天前的主题,其中的信息可能已经有所发展或是发生改变。

    报错如下:

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

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

    项目目录结构如下:

    │  index.html
    │  package-lock.json
    │  package.json
    │  tsconfig.json
    ├─bin
    │      game.js
    │      game.js.map
    │      main.js
    │      main.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"
        ]
    }
    
    第 1 条附言  ·  353 天前

    通过配置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;
        
            #   表示允许这个域跨域调用(客户端发送请求的域名和端口) 
            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;
        ```
    7 条回复    2023-05-07 16:23:42 +08:00
    gucheen
        1
    gucheen  
       353 天前   ❤️ 1
    是 feature 不是 bug ,参见
    https://github.com/microsoft/TypeScript/issues/16577
    你这个情况可以考虑自己对编译后的文件二次处理,或者在你的服务器上做 rewrite
    leokun
        2
    leokun  
       353 天前
    用什么工具编译的
    z888888cn
        3
    z888888cn  
    OP
       353 天前
    @leokun 执行`npx tsc`,编译 Typescript 生成的 JavaScript 脚本。
    DOLLOR
        4
    DOLLOR  
       353 天前
    main.ts 里把
    import { Game } from './game';
    改为
    import { Game } from './game.js';
    z888888cn
        5
    z888888cn  
    OP
       353 天前
    @gucheen 感谢,我通过 nginx 配置解决了。但是 nginx 配置看着有点懵懵的。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;
    ```
    leokun
        6
    leokun  
       353 天前
    @z888888cn tsc 不太适合 web 工具库的构建,例如路径别名(path)和拓展名都不支持
    ts 库的选择 tsup 或者 rollup ,前者用 tsc 构建 d.ts ,用 esbuild 构建 js
    web 应用就很多选择了,vite 、webpack 等

    如果想要在 node 直接运行 ts ,tsx(不是 react 的 tsx)也是不错的选择
    z888888cn
        7
    z888888cn  
    OP
       352 天前
    @leokun 非常感谢,我用 rollup 编译 ts 脚本,超级方便。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1049 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 22:30 · PVG 06:30 · LAX 15:30 · JFK 18:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.