繁体   English   中英

Node本身可以在没有express或任何其他模块的情况下提供静态文件..?

[英]Node itself can serve static files without express or any other module..?

我是节点 js 领域的初学者。不知道如何从 url 发送简单请求,例如:- http://localhost:9999/xyz/inde.html我的文件层次结构是

server.js
xyz(folder)-
          |->index.html

并从我的服务器获取 html 页面。它在 9999 后运行

var http = require("http");
function onRequest(request, response) {
console.log("Request received.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.end();
}
http.createServer(onRequest).listen(9999);
console.log("Server has started.");

我知道我可以从节点 js 服务器发送字符串(具有 html 模板)并发送它作为响应,但是如何在没有 express 和任何其他外部模块的情况下发送文件。 谢谢

尝试创建一个没有npm依赖项的节点应用程序是荒谬的,因为 nodejs 的基础就是——一个基础。 除非你想实现整个协议,否则最好使用一个最小的、维护良好的npm模块来为你做这npm 也就是说,这是您要求的非常基本的东西(没有 MiME、eTags、缓存等):

var basePath = __dirname;
var http = require('http');
var fs = require('fs');
var path = require('path');

http.createServer(function(req, res) {
    var stream = fs.createReadStream(path.join(basePath, req.url));
    stream.on('error', function() {
        res.writeHead(404);
        res.end();
    });
    stream.pipe(res);
}).listen(9999);

 const http = require('http'); const fs = require("fs"); const path = require("path"); function send404(response){ response.writeHead(404, {'Content-Type': 'text/plain'}); response.write('Error 404: Resource not found.'); response.end(); } const mimeLookup = { '.js': 'application/javascript', '.html': 'text/html' }; const server = http.createServer((req, res) => { if(req.method == 'GET'){ let fileurl; if(req.url == '/'){ fileurl = 'index.html'; }else{ fileurl = req.url; } let filepath = path.resolve('./' + fileurl); let fileExt = path.extname(filepath); let mimeType = mimeLookup[fileExt]; if(!mimeType) { send404(res); return; } fs.exists(filepath, (exists) => { if(!exists){ send404(res); return; } res.writeHead(200, {'Content-Type': mimeType}); fs.createReadStream(filepath).pipe(res); }); } }).listen(3000); console.log("Server running at port 3000");

它非常简单,节点已经提供了 fs 模块,您可以从中读取该 html 文件并附加在响应 obj 上,如下所示:

response.writeHead(200, {"Content-Type": "text/plain"});
//here is the code required
fs.readFile("./xyz/index.html", (err,fileContent) =>
{
  response.end(fileContent);
});

但这里的问题是你只会得到 HTML 文档,而不是那些存储在不同文件夹中的 HTML 文件中的资源,就像你的 index.html 中有这个代码一样

<link rel="stylesheet" href="../css/index.css" />

节点服务器将不允许此 index.css。 但我想你的问题已经解决了。

我不同意接受的答案中的断言:

“尝试创建一个没有 npm 依赖项的节点应用程序是荒谬的”

由于具有零依赖项,因此您只需复制 javascript 文件即可将应用程序部署到运行 node 的系统,而无需运行npm install

我发现这在现实生活中很有用的一个例子是编写一个公共 API 来计算企业需要从员工工资中扣除的所得税金额。 你可以在这里阅读关于这个有趣话题的所有内容但本质上我有一个 api,它通过了总收入并返回了总收入应如何在净收入和税收之间分配。

我用一个单独的 index.js 文件做到了这一点,没有 package.json,并且需要npm install

索引.js:

http = require('http');
url = require('url');
const port = 80; // make this a number over 1024 if you want to run `node` not run `sudo node` 
const debug = true;
const httpServer = http.createServer((request, response) => {
  response.setHeader('Content-Type', 'application/json');
  const parsedUrl = url.parse(request.url, true);
  let pathName = parsedUrl.pathname;
  if (pathName==='/favicon.ico') {
    // chrome calls this to get an icon to display in the tab. I want to ignore these request. They only happen when testing in a browser,
    // not when this api is called in production by a non-browser.
    if (debug) console.log('Browser requested favicon.ico')
    response.end();
    
  } else {
    if (debug) console.log('Request on path ' + pathName);
    const elements = pathName.split('/');
    if (elements.length == 3 && elements[0] === '' &&  elements[1]==='witholdcalc') {
      const grossString = elements[2];
      const gross = Number.parseInt(grossString);
      if (isNaN(gross)) {
        response.writeHead(400).end(JSON.stringify({error:'Gross salary must be an integer. found: ' + grossString}));
      } else {
        /*
         * The computation of the amount to withold is more complicated that this, but it could still be hard coded here:
         * For simplicity, I will compute in one line:
         */
        const withold = Math.floor((gross<1000)?0:((gross-1000)*.2));
        response.writeHead(200).end(JSON.stringify({net: (gross-withold), withold: withold, elements:(debug?elements:undefined)}));
      }
    } else {
      if (debug) console.log('Invalid path was: ' + pathName,elements);
      response.writeHead(404).end();
    }
  }
});
httpServer.listen(port), () => {
  console.log(`PAYG listening at http://localhost:${port}`)
}

然后我可以在我的 linux 计算机上执行sudo node install.js ,并在浏览器中,点击http://localhost/witholdcalc/6000 ,它会在调试时返回 {"net":5000,"withold":1000}设置为假。

任何试图在没有 Express 或任何其他框架的情况下提供静态文件的人,请注意:

在性能或生产力方面,跳过 Express 没有任何好处。 唯一的例外是了解服务器和客户端如何相互通信。 像 Express 这样的框架抽象了所有这些复杂性,初学者可能无法完全理解它们的工作原理。

这是我仅使用 Node.js 提供静态文件的方法。 实际上,我这样做的原因是因为给我的编码测试没有规定任何框架。

  1. 首先,决定这些静态文件的 URL 路径应该是什么样的。 我希望我的可以在/assets/路径下访问,例如https://example.com/assets/main.csshttps://example.com/assets/cat.jpg

  2. 决定匹配这些 URL 的 REGEX。 `const assetPattern = /^/assets/[a-zA-Z]+.[a-zA-Z]+/;

上面的公式将匹配包含/assets/[filename].[file extension url。

  1. 使用 Node.js 创建服务器,将回调函数作为参数。
// ...
const http = require('http')
const server = http.createServer(requestListener).
  1. 提取 url 路径,获取相应的文件路径并配置您的服务器以将正确的 MIME 类型发送到浏览器。
const path = require('path');
// ...
const requestListener = (req, response) => {
  // get the relative url for the request. For example, relative url for a request  
  // to https://example.com is /.
  const { url } = req;
  if (url.match(assetPattern)) {
  // Inside the project directory, the static files are located under the
  // /public/assets directory.
    const filePath = `./public/${url}`;
  // Get the extension name aka the string after the dot. For example, a url like 
  // https://example.com/assets/main.css will result in extension name of css.
    const extname = String(path.extname(filePath)).toLowerCase();
    const mimeTypes = {
      '.html': 'text/html',
      '.js': 'text/javascript',
      '.css': 'text/css',
      '.json': 'application/json',
      '.png': 'image/png',
      '.jpg': 'image/jpg',
      '.gif': 'image/gif',
      '.svg': 'image/svg+xml',
      '.wav': 'audio/wav',
      '.mp4': 'video/mp4',
      '.woff': 'application/font-woff',
      '.ttf': 'application/font-ttf',
      '.eot': 'application/vnd.ms-fontobject',
      '.otf': 'application/font-otf',
      '.wasm': 'application/wasm',
    };
    const contentType = mimeTypes[extname] || 'application/octet-stream';
    staticFileHandler(req, response, filePath, contentType);
  }
}
  1. 使用fs模块提供静态文件
const fs = require('fs')
// ...
const staticFileHandler = (req, res, filePath, contentType) => {
  fs.readFile(filePath, (err, content) => {
    if (err) {
      res.writeHead(500);
      res.end(`Sorry, check with the site admin for error: ${err.code}`)
    } else {
      res.writeHead(200, { 'Content-Type': contentType }); // indicate the request was successful
      res.end(content, 'utf-8');
    }
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM