Webpack 없이 NodeJS에서 파일을 가져오는 방법

범용 앱, 테스트 또는 단순히 상용구를 피하기 위해 임의의 파일을 직접 가져오는 것이 도움이 되는 경우가 꽤 있습니다. 좋은 소식: Babel, Webpack 또는 다른 것이 필요하지 않습니다.

이 자습서에서는 모듈로 로드된 CSS 스타일로 정적 HTML 페이지를 렌더링하는 서버를 만들 것입니다.

CSS 파일을 만듭니다.

echo 'html{background:teal;color:white;}' >> styles.css


HTML 템플릿:

echo '<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Example</title>
  </head>
  <body>
    Is background teal?
  </body>
</html>' >> template.html


그리고 결과를 렌더링하는 서버:

// index.js
const http = require("http");
const template = require("./template.html");
const css = require("./styles.css");
const html = template.replace("</head>", "<style>" + css + "</style></head>");

const server = new http.Server((_req, res) => {
  res.setHeader("content-type", "text/html");
  res.end(html);
});

server.listen(0, () => {
  console.info(
    `Server is listening on http://localhost:${server.address().port}`
  );
});


지금 이 파일을 실행하려고 하면 오류가 발생합니다.

node index
template.html:1
<!DOCTYPE html>
^

SyntaxError: Unexpected token '<'


이를 수정하기 위해 NodeJS에 이러한 확장을 처리하는 방법을 알려줄 것입니다. 필요한 모든 코드는 다음과 같기 때문에 놀랄 준비를 하십시오.

// hook.js
const Module = require("module");
const fs = require("fs");

const resolveTextFile = function (module, path) {
  const content = fs.readFileSync(path).toString();
  module.exports = content;
};

Module._extensions[".html"] = resolveTextFile;
Module._extensions[".css"] = resolveTextFile;


이제 다음과 같이 서버를 시작할 수 있습니다.

node -r ./hook index
# Server is listening on http://localhost:<random_port>


링크를 따라가면 적절한 스타일의 HTML 페이지가 표시됩니다.



Note: If you have any troubles running this example, try using NodeJS v14.5.0.



그런데 require('./hook') 또는 index.js 명령줄 인수를 사용하는 대신 -r의 시작 부분에 --require을 직접 추가할 수 있습니다.

ECMAScript 모듈은 어떻습니까?



좋은 질문입니다! NodeJS의 ECMAScript 모듈 지원은 여전히 ​​불안정하여 향후 크게 변경될 수 있지만 2021년 2월에는 node --experimental-loader <filename> 으로 사용자 정의 모듈을 로드할 수 있습니다.

내 ECMAScript 서버 모듈은 다음과 같습니다.

// index.mjs
import http from "http";
import template from "./template.html";
import css from "./styles.css";

const html = template.replace("</head>", "<style>" + css + "</style></head>");

const server = new http.Server((_req, res) => {
  res.setHeader("content-type", "text/html");
  res.end(html);
});

server.listen(0, () => {
  console.info(
    `Server module is listening on http://localhost:${server.address().port}`
  );
});


그리고 experimental loader은 다음과 같습니다.

// loader.mjs
import { URL, pathToFileURL } from "url";

const baseURL = pathToFileURL(`${process.cwd()}/`).href;

// css styles or html files
const extensionsRegex = /\.(html|css)$/;

export function resolve(specifier, context, defaultResolve) {
  const { parentURL = baseURL } = context;

  // Node.js normally errors on unknown file extensions, so return a URL for
  // specifiers ending in the specified file extensions.
  if (extensionsRegex.test(specifier)) {
    return {
      url: new URL(specifier, parentURL).href,
    };
  }
  // Let Node.js handle all other specifiers.
  return defaultResolve(specifier, context, defaultResolve);
}

export function getFormat(url, context, defaultGetFormat) {
  // Now that we patched resolve to let new file types through, we need to
  // tell Node.js what format such URLs should be interpreted as.
  if (extensionsRegex.test(url)) {
    return {
      format: "module",
    };
  }
  // Let Node.js handle all other URLs.
  return defaultGetFormat(url, context, defaultGetFormat);
}

export function transformSource(source, context, defaultTransformSource) {
  const { url } = context;
  if (extensionsRegex.test(url)) {
    return {
      source: `export default ${JSON.stringify(source.toString())}`,
    };
  }

  // Let Node.js handle all other sources.
  return defaultTransformSource(source, context, defaultTransformSource);
}



ES 모듈에 .mjs 확장을 사용하거나 그렇지 않으면 활성화하는 것을 잊지 마십시오(예: "type":"module" 에서 package.json 설정).

그리고 다음과 같이 실행하십시오:

node --experimental-loader ./loader.mjs index.mjs
# (node:14706) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time
# (Use `node --trace-warnings ...` to show where the warning was created)
# ESM Server is listening on http://localhost:<random_port>


TypeScript는 어떻습니까?



또 다른 좋은 질문입니다! 실제로는 쉽습니다. CommonJS 접근 방식을 사용할 수 있습니다.

TypeScript 프로젝트를 준비합시다.

npm init -y &&
npm install typescript @types/node ts-node --save-dev &&
echo '{
  "compilerOptions": {
    "target": "ES2020",
    "module": "CommonJS",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "typeRoots": ["node_modules/@types", "typings"]
  },
  "exclude": ["node_modules"]
}
'>>tsconfig.json



esModuleInterop을 true로 설정하여 hook.js을 그대로 유지했습니다. 그렇지 않으면 module.exports=contentmodule.exports.default=content으로 변경해야 합니다.

내가 입력한 악명 높은 서버 버전:

// index.ts
import { Server } from "http";
import template from "./template.html";
import css from "./styles.css";
import { AddressInfo } from "net";

const html = template.replace("</head>", "<style>" + css + "</style></head>");

const server = new Server((_req, res) => {
  res.setHeader("content-type", "text/html");
  res.end(html);
});

server.listen(0, () => {
  console.info(
    `TS Server is listening on http://localhost:${
      (server.address() as AddressInfo).port
    }`
  );
});



다시 한 번 지금 실행하면 실패합니다.

./node_modules/.bin/ts-node -r ./hook index.ts

# TSError: ⨯ Unable to compile TypeScript:
# index.ts:2:22 - error TS2307: Cannot find module './template.html' or its corresponding type declarations.


이를 수정하려면 물론 모듈에 대한 타이핑을 제공해야 합니다. ts-node을 사용할 것이므로 가장 쉬운 방법은 다음 구조로 폴더를 만드는 것입니다.

mkdir -p "typings/*.css" &&
mkdir "typings/*.html" &&
echo 'declare module "*.css" {
  const content: string;
  export default content;
}' >> "typings/*.css/index.d.ts" &&
echo 'declare module "*.html" {
  const content: string;
  export default content;
}' >> "typings/*.html/index.d.ts" 


우리는 이미 tsconfig.json 에 typings 폴더를 포함했지만 참조되는 한 원하는 이름으로 부를 수 있습니다.

{
  "compilerOptions": {
    // ...
    "typeRoots": ["node_modules/@types", "typings"]
  },
  // ...
}


다시 실행하고 상쾌한 청록색 배경을 즐기십시오.

./node_modules/.bin/ts-node -r ./hook index.ts
# TS Server is listening on http://localhost:<random_port>


다음은 무엇입니까?



다음을 수행할 수 있습니다.

7 109106
  • sass 파일을 직접 사용하여 GraphQL 서버를 만듭니다.
  • 경량 또는 사용자 정의 테스트 러너를 사용하여 프론트 엔드 JavaScript에 대한 단위 테스트를 작성하십시오.
  • 나만의 코드 변환기/번들러 만들기

  • 읽어 주셔서 감사합니다! 당신이 그것을 즐겼기를 바랍니다!

    좋은 웹페이지 즐겨찾기