NodeJS 类型错误[错误未知文件扩展名]:未知的文件扩展名". json"

hc2pp10m  于 2023-01-08  发布在  Node.js
关注(0)|答案(1)|浏览(274)
  • 嗨,开发人员!*命令:=〉跨环境NODE_ENV =生产节点服务器. mjs

错误

node:internal/errors:464
    ErrorCaptureStackTrace(err);
    ^

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".json" for /home/windows/Documents/workspace/{projectPath}/dist/client/ssr-manifest.json
    at new NodeError (node:internal/errors:371:5)
    at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:87:11)
    at defaultGetFormat (node:internal/modules/esm/get_format:102:38)
    at defaultLoad (node:internal/modules/esm/load:21:14)
    at ESMLoader.load (node:internal/modules/esm/loader:359:26)
    at ESMLoader.moduleProvider (node:internal/modules/esm/loader:280:58)
    at new ModuleJob (node:internal/modules/esm/module_job:66:26)
    at ESMLoader.#createModuleJob (node:internal/modules/esm/loader:297:17)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:261:34)
    at async Promise.all (index 0) {
  code: 'ERR_UNKNOWN_FILE_EXTENSION'
}

我的配置:

  • 第3.x.x版
  • typescript
  • 版本4.x.x
  • 版本3.2.x
  • 使用vite进行服务器端渲染

我做到了

  • entry-server.js
  • entry-client.ts
  • server.js

正在发生什么

  • "dev":"节点服务器. mjs",==〉工作正常
  • "build":"npm运行构建:客户端&& npm运行构建:服务器",=〉工作正常
  • "serve":"跨环境NODE_ENV =生产节点服务器. mjs",=〉错误。
    请帮助我解决此问题。

我的服务器. mjs文件

// @ts-check
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import express from 'express';

const isTest = process.env.NODE_ENV === 'test' || !!process.env.VITE_TEST_BUILD;

export async function createServer(
  root = process.cwd(),
  isProd = process.env.NODE_ENV === 'production',
  hmrPort
) {
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
  const resolve = (p) => path.resolve(__dirname, p);

  const indexProd = isProd ? fs.readFileSync(resolve('dist/client/index.html'), 'utf-8') : '';

  const manifest = isProd
    ? // @ts-ignore
      (await import('./dist/client/ssr-manifest.json')).default
    : {};

  const app = express();

  /**
   * @type {import('vite').ViteDevServer}
   */
  let vite;
  if (!isProd) {
    vite = await (
      await import('vite')
    ).createServer({
      base: '/',
      root,
      logLevel: isTest ? 'error' : 'info',
      server: {
        middlewareMode: true,
        watch: {
          // During tests we edit the files too fast and sometimes chokidar
          // misses change events, so enforce polling for consistency
          usePolling: true,
          interval: 100,
        },
        hmr: {
          port: hmrPort,
        },
      },
      appType: 'custom',
    });
    // use vite's connect instance as middleware
    app.use(vite.middlewares);
  } else {
    app.use((await import('compression')).default());
    app.use(
      '/test/',
      (await import('serve-static')).default(resolve('dist/client'), {
        index: false,
      })
    );
  }

  app.use('*', async (req, res) => {
    try {
      const url = req.originalUrl.replace('/test/', '/');

      let template, render;
      if (!isProd) {
        // always read fresh template in dev
        template = fs.readFileSync(resolve('index.html'), 'utf-8');
        template = await vite.transformIndexHtml(url, template);
        render = (await vite.ssrLoadModule('/src/entry-server.js')).render;
      } else {
        template = indexProd;
        // @ts-ignore
        render = (await import('./dist/server/entry-server.js')).render;
      }

      const [appHtml, preloadLinks] = await render(url, manifest);

      const html = template
        .replace(`<!--preload-links-->`, preloadLinks)
        .replace(`<!--app-html-->`, appHtml);

      res.status(200).set({ 'Content-Type': 'text/html' }).end(html);
    } catch (e) {
      vite && vite.ssrFixStacktrace(e);
      console.log(e.stack);
      res.status(500).end(e.stack);
    }
  });

  return { app, vite };
}

if (!isTest) {
  createServer().then(({ app }) =>
    app.listen(4400, () => {
      console.log('http://localhost:4400');
    })
  );
}

这是我的视频配置

/* import { fileURLToPath, URL } from 'node:url';

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
    },
  },
});
 */

import path from 'node:path';
import type { UserConfig } from 'vite';
import vuePlugin from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import { fileURLToPath, URL } from 'node:url';
const virtualFile = '@virtual-file';
const virtualId = '\0' + virtualFile;
const nestedVirtualFile = '@nested-virtual-file';
const nestedVirtualId = '\0' + nestedVirtualFile;

const base = '/';

// preserve this to test loading __filename & __dirname in ESM as Vite polyfills them.
// if Vite incorrectly load this file, node.js would error out.
globalThis.__vite_test_filename = __filename;
globalThis.__vite_test_dirname = __dirname;

export default ({ command, ssrBuild }) => {
  const config: UserConfig = {
    base,
    plugins: [
      vuePlugin(),
      vueJsx(),

      {
        name: 'virtual',
        resolveId(id) {
          if (id === '@foo') {
            return id;
          }
        },
        load(id, options) {
          const ssrFromOptions = options?.ssr ?? false;
          if (id === '@foo') {
            // Force a mismatch error if ssrBuild is different from ssrFromOptions
            return `export default { msg: '${
              command === 'build' && !!ssrBuild !== ssrFromOptions
                ? `defineConfig ssrBuild !== ssr from load options`
                : 'hi'
            }' }`;
          }
        },
      },
      {
        name: 'virtual-module',
        resolveId(id) {
          if (id === virtualFile) {
            return virtualId;
          } else if (id === nestedVirtualFile) {
            return nestedVirtualId;
          }
        },
        load(id) {
          if (id === virtualId) {
            return `export { msg } from "@nested-virtual-file";`;
          } else if (id === nestedVirtualId) {
            return `export const msg = "[success] from conventional virtual file"`;
          }
        },
      },
      // Example of a plugin that injects a helper from a virtual module that can
      // be used in renderBuiltUrl
      (function () {
        const queryRE = /\?.*$/s;
        const hashRE = /#.*$/s;
        const cleanUrl = (url: string) => url.replace(hashRE, '').replace(queryRE, '');
        let config;

        const virtualId = '\0virtual:ssr-vue-built-url';
        return {
          name: 'built-url',
          enforce: 'post',
          configResolved(_config) {
            config = _config;
          },
          resolveId(id) {
            if (id === virtualId) {
              return id;
            }
          },
          load(id) {
            if (id === virtualId) {
              return {
                code: `export const __ssr_vue_processAssetPath = (url) => '${base}' + url`,
                moduleSideEffects: 'no-treeshake',
              };
            }
          },
          transform(code, id) {
            const cleanId = cleanUrl(id);
            if (
              config.build.ssr &&
              (cleanId.endsWith('.js') || cleanId.endsWith('.vue')) &&
              !code.includes('__ssr_vue_processAssetPath')
            ) {
              return {
                code:
                  `import { __ssr_vue_processAssetPath } from '${virtualId}';__ssr_vue_processAssetPath;` +
                  code,
                sourcemap: null, // no sourcemap support to speed up CI
              };
            }
          },
        };
      })(),
    ],
    resolve: {
      alias: {
        '@': fileURLToPath(new URL('./src', import.meta.url)),
      },
    },
    experimental: {
      renderBuiltUrl(filename, { hostType, type, ssr }) {
        if (ssr && type === 'asset' && hostType === 'js') {
          return {
            runtime: `__ssr_vue_processAssetPath(${JSON.stringify(filename)})`,
          };
        }
      },
    },
    build: {
      minify: false,
    },
    ssr: {
      noExternal: [
        // this package has uncompiled .vue files
        'example-external-component',
      ],
    },

    optimizeDeps: {
      exclude: ['example-external-component'],
    },
  };

  return config;
};

我所尝试的

我添加了cross-env NODE_ENV=production node --experimental-json-modules server.js
但我得到了另一种类型的错误。

错误

node:internal/errors:464
    ErrorCaptureStackTrace(err);
    ^

TypeError [ERR_IMPORT_ASSERTION_TYPE_MISSING]: Module "file:///home/windows/Documents/workspace/{projectPath}/dist/client/ssr-manifest.json" needs an import assertion of type "json"
    at new NodeError (node:internal/errors:371:5)
    at validateAssertions (node:internal/modules/esm/assert:82:15)
    at defaultLoad (node:internal/modules/esm/load:24:3)
    at ESMLoader.load (node:internal/modules/esm/loader:359:26)
    at ESMLoader.moduleProvider (node:internal/modules/esm/loader:280:58)
    at new ModuleJob (node:internal/modules/esm/module_job:66:26)
    at ESMLoader.#createModuleJob (node:internal/modules/esm/loader:297:17)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:261:34)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:337:24) {
  code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING'
}
kknvjkwl

kknvjkwl1#

当我尝试为我的服务器导入一个JSON时,我也遇到了同样的错误。
需要类型为“json”的导入Assert
我决定:

import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);

const exemple = require('./data/exemple.json');

在json.file中使用此函数,节点将重新识别导入。
另一个例子:

import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const swaggerDocs = require("./swagger.json");

相关问题