Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simple node http server for webpack dev #1729

Merged
merged 12 commits into from
Sep 1, 2020
20 changes: 0 additions & 20 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# Created by https://www.gitignore.io/api/osx,windows,linux,xcode,objective-c,swift,android,java,jetbrains,eclipse,sublimetext,node,vim,netbeans,emacs,vagrant,textmate,otto,gradle

### OSX ###
Expand All @@ -9,7 +8,6 @@
# Icon must end with two \r
Icon


# Thumbnails
._*

Expand All @@ -28,7 +26,6 @@ Network Trash Folder
Temporary Items
.apdisk


### Windows ###
# Windows image file caches
Thumbs.db
Expand All @@ -49,7 +46,6 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk


### Linux ###
*~

Expand All @@ -62,7 +58,6 @@ $RECYCLE.BIN/
# Linux trash folder which might appear on any partition or disk
.Trash-*


### Xcode ###
# Xcode
#
Expand All @@ -88,7 +83,6 @@ xcuserdata
*.moved-aside
*.xcuserstate


### Objective-C ###
# Xcode
#
Expand Down Expand Up @@ -147,7 +141,6 @@ fastlane/screenshots
### Objective-C Patch ###
*.xcscmblueprint


### Swift ###
# Xcode
#
Expand Down Expand Up @@ -209,7 +202,6 @@ Carthage/Build
fastlane/report.xml
fastlane/screenshots


### Android ###
# Built application files
*.apk
Expand Down Expand Up @@ -246,7 +238,6 @@ captures/
### Android Patch ###
gen-external-apklibs


### Java ###
*.class

Expand All @@ -261,7 +252,6 @@ gen-external-apklibs
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*


### JetBrains ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm

Expand Down Expand Up @@ -312,7 +302,6 @@ crashlytics.properties
crashlytics-build.properties
fabric.properties


### Eclipse ###
*.pydevproject
.metadata
Expand Down Expand Up @@ -355,7 +344,6 @@ local.properties
# STS (Spring Tool Suite)
.springBeans


### SublimeText ###
# cache files for sublime text
*.tmlanguage.cache
Expand All @@ -372,7 +360,6 @@ local.properties
# sftp configuration file
sftp-config.json


### Node ###
# Logs
logs
Expand Down Expand Up @@ -409,7 +396,6 @@ node_modules
# Optional REPL history
.node_repl_history


### Vim ###
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
Expand All @@ -418,7 +404,6 @@ Session.vim
.netrwhist
*~


### NetBeans ###
nbproject/private/
build/
Expand All @@ -428,7 +413,6 @@ nbdist/
nbactions.xml
.nb-gradle/


### Emacs ###
# -*- mode: gitignore; -*-
*~
Expand Down Expand Up @@ -463,21 +447,17 @@ tramp
# cask packages
.cask/


### Vagrant ###
.vagrant/


### TextMate ###
*.tmproj
*.tmproject
tmtags


### Otto ###
.otto/


### Gradle ###
.gradle
build/
Expand Down
91 changes: 91 additions & 0 deletions packages/xarc-app-dev/src/lib/dev-admin/dev-http.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import { createReadStream } from "fs";
import { createServer, IncomingMessage, RequestListener, ServerResponse } from "http";
import * as Url from "url";
import { resolve } from "path";
const Middleware = require("./middleware");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think middleware is typed, so you can import it normally


export interface DevHttpServerOptions {
port: number;
host: string;
protocol?: string;
}

export type HttpRequestEvent = "connect" | "response" | "timeout" | "close" | "finish";
export type HttpServerEvent = "open" | "close" | "listening" | "error";

export interface DevHttpServer {
webpackDevHttpPlugin: RequestListener;
start: () => void;
stop?: () => void;
addRequestListener: (event: HttpRequestEvent, handler: any) => void;
addServerEventListener: (event: HttpServerEvent, hander: any) => void;
}

export const setupHttpDevServer = function({
port,
host,
protocol = "http"
}: DevHttpServerOptions): DevHttpServer {
const middleware = new Middleware({
baseUrl: () => {
return Url.format({
hostname: host || process.env.HOST || "localhost",
protocol: protocol, // doesn't matter since it's a downstream call anyway..
port: port || process.env.PORT
});
}
});

middleware.setup();

const requestEventHooks = {};

const webpackDevHttpPlugin: RequestListener = function(
req: IncomingMessage,
res: ServerResponse
) {
Object.keys(requestEventHooks).map(eventName => {
req.addListener(eventName, event => requestEventHooks[eventName]({ ...event, ...req }));
});
middleware.process(req, res, {
skip: () => Promise.resolve(),
replyHtml: html => {
res
.writeHead(200, {
"Content-Type": "text/html"
})
.end(`<!DOCTYPE html>${html}`);
},
replyError: err => {
res.writeHead(500, err);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is res.end() needed?

},
replyNotFound: () => res.writeHead(404, "dev server express Not Found"), //res.status(404).send("dev server express Not Found"),
replyStaticData: data => {
const type = require("mime").getType(req.url);
res.writeHead(200, {
"Content-Type": type
});
res.end(data);
},
replyFile: file => createReadStream(resolve(file)).pipe(res)
});
};
const server = createServer(webpackDevHttpPlugin);

return {
start: () => server.listen(port, host),
webpackDevHttpPlugin,
addServerEventListener: (event: HttpServerEvent, cb) => {
server.addListener(event.toString(), cb);
},
stop: () => {
server.close(function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is asynchronous, it's a good idea to make this return a promise?

/* eslint-disable no-console */
console.log("Server closed!");
});
},
addRequestListener: (event: HttpRequestEvent, cb: any) => (requestEventHooks[event] = cb)
};
};
export const setup = setupHttpDevServer;
20 changes: 17 additions & 3 deletions packages/xarc-app-dev/src/lib/dev-admin/dev-server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-var-requires */
export {};

/* eslint-disable global-require, no-console */
import { DevHttpServer, setupHttpDevServer } from "./dev-http";
import { createServer } from "http";

const ck = require("chalker");
const archetype = require("../../config/archetype")();
Expand All @@ -20,7 +20,21 @@ if (process.env.WEBPACK_DEV === undefined) {
process.env.WEBPACK_DEV = "true";
}

if (fastifyServer) {
if (createServer) {
const devHttpServer: DevHttpServer = setupHttpDevServer({
host: archetype.webpack.devHostname,
port: archetype.webpack.devPort
});
devHttpServer.start();
devHttpServer.addServerEventListener("error", err => {
console.error(ck`<red>HTTP webpack dev server having an error</>${err}`);
});
devHttpServer.addServerEventListener("listening", e => {
console.log(
ck`<green>Node.js webpack dev server listening on port ${archetype.webpack.devPort}</>`
);
});
} else if (fastifyServer) {
fastifyServer({
electrode: {
logLevel: "warn",
Expand Down
50 changes: 50 additions & 0 deletions packages/xarc-app-dev/test/spec/dev-admin/dev-http.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-empty-function */
// /* eslint-disable @typescript-eslint/ban-ts-ignore, no-invalid-this, @typescript-eslint/class-name-casing */

// const mockRequire = require("mock-require");

// const moduleName = "../../../lib/dev-admin/dev-http";

// import { before, beforeEach, describe, it, after, afterEach } from "mocha";
// import { expect } from "chai";
// import * as Axios from "axios";

// describe("dev-http", function() {
// this.timeout(10000);
// let server;
// ]
// before(() => {});

// beforeEach(() => {
// const setupServer = require("../../../lib/dev-admin/dev-http").setup;

// const textCycle = () => {};
// server = setupServer({ port: 3003, host: "localhost" });
// server.start();
// });

// afterEach(() => {
// delete require.cache[require.resolve(moduleName)];
// server.stop();
// });

// after(() => {
// mockRequire.stop("@xarc/app/config/archetype");
// mockRequire.stop("../../src/lib/dev-admin/middleware");
// });

// describe("setup", () => {
// it.skip("http server: if replyFile is called with a valid file then return 200", () => {
// Axios.default.get("http://localhost:3003/").then(resp => {
// expect(resp.status).to.equal(200);
// });
// });

// // it("if replyFile is called with an invalid file then return 404", () => {
// // textCycle(cycle => {
// // const { result } = cycle.replyFile("./xclap.bs");
// // expect(result.code).to.equal(404);
// // });
// // });
// });
// });
3 changes: 1 addition & 2 deletions samples/poc-subapp-min-fastify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@
},
"fyn": {
"dependencies": {
"@xarc/app": "../../packages/xarc-app",
"@xarc/fastify-server": "../../../fastify-server"
"@xarc/app": "../../packages/xarc-app"
},
"devDependencies": {
"@xarc/app-dev": "../../packages/xarc-app-dev"
Expand Down
Loading