diff --git a/packages/build/lib/server.js b/packages/build/lib/server.js index 83bc956f1..1197e5b07 100644 --- a/packages/build/lib/server.js +++ b/packages/build/lib/server.js @@ -23,6 +23,7 @@ process.on('unhandledRejection', function(error) { function runDevelop(options, callback) { var compiler = webpack(developConfig); var app = express(); + app.use(hopsExpressUtils.timings); app.use( webpackDevMiddleware(compiler, { noInfo: true, diff --git a/packages/config/README.md b/packages/config/README.md index f9484b23a..d24234d38 100644 --- a/packages/config/README.md +++ b/packages/config/README.md @@ -19,28 +19,28 @@ Please find a list of the default options below. They can be set in your project ## Available Options -| Field | Type | Description | -| --------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `https` | `Boolean` | Whether to use https or not. Defaults to `false` | -| `host` | `String` | Host name of your project. Defaults to `0.0.0.0` | -| `port` | `Number` | Port of your host. Defaults to `8080` | -| `locations` | `Array` | One or more [application shell](https://developers.google.com/web/fundamentals/architecture/app-shell) locations, e.g. `"/"` and/or `"/profile"` | -| `basePath` | `String` | Root path of your application on the server. This is inserted as an HTTP path prefix between `host` and `locations`. For example, if you set e.g. `"basePath": "my-custom-basepath"` and `"location": ["/profile"]`, then your application would be available at `http://0.0.0.0:8080/my-custom-basepath/profile/` | -| `assetPath` | `String` | HTTP root path of your asset files on the server. It's not dependent on `basePath`, you can define totally separate directories | -| `browsers` | `String` | [Browserslist](https://www.npmjs.com/package/browserslist) query. Defaults to `"> 1%, last 2 versions, Firefox ESR"` (which is also the Browserlist default query). It is used for Babel and PostCSS | -| `node` | `String` | [Node target version](https://www.npmjs.com/package/babel-preset-env#targetsnode). Defaults to `current`. It is used to specify the Node version which Babel should compile for | -| `envVars` | `{ HOPS_MODE: 'dynamic' }` | Environment variables meant to be passed to [`webpack.EnvironmentPlugin`](https://webpack.js.org/plugins/environment-plugin/), i.e. made accessible to your app | -| `moduleDirs` | `Array` | One or more directories that Hops should use for module path resolution. For example, you can specify a directory that holds a yet unpublished Node.js package. It works similar to the [resolve.modulesDirectories](http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories) field in Webpack, i.e. if you specify `moduleDirs: ["my-module-dir"]`, it will look in `./my-module-dir`, `../my-module-dir`, `../../my-module-dir` and so on | -| `appDir` | `String` | Directory of your app. This way, you can put your app to a place other than project root. Defaults to `"."` | -| `buildDir` | `String` | Directory where the build artifacts (i.e. your application/asset files) will be saved to. Defaults to `"build"`. Hops always removes the specified directory before starting a new build | -| `cacheDir` | `String` | Directory where internally used artifacts not meant to be served will be output (e.g. the `manifest.json`/`manifest.js` files generated by Webpack). Defaults to `"node_modules/.cache/hops"` | -| `buildConfig` | `String` | Path to your Webpack build configuration file. Defaults to `undefined` - use this option in your `package.json` to overwrite the default configuration. Read more about it at [hops-build-config](https://github.com/xing/hops/tree/master/packages/build-config#available-options) | -| `developConfig` | `String` | Path to your Webpack development configuration file. Defaults to `undefined` - use this option in your `package.json` to overwrite the default configuration. Read more about it at [hops-build-config](https://github.com/xing/hops/tree/master/packages/build-config#available-options) | -| `nodeConfig` | `String` | Path to your Webpack node/server-side rendering configuration file. Defaults to `undefined` - use this option in your `package.json` to overwrite the default configuration. Read more about it at[hops-build-config](https://github.com/xing/hops/tree/master/packages/build-config#available-options) | -| `manifest` | `String` | The application's `manifest.js` as a string. Defaults to a getter function that returns the content of the automatically generated `manifest.js` | -| `extends` | `String` | Path to a baseline configuration (could be for example a node module or a project-specific file), allowing you join the current configuration with that baseline | - -All keys matching `/(config|file|dir)s?$/i` will be treated as a filesystem path (or array thereof) and resolved relative to your app's root folder. This only applies if the respective value is not an absolute path already. +| Field | Type | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `https` | `Boolean` | Whether to use https or not. Defaults to `false` | +| `host` | `String` | Host name of your project. Defaults to `0.0.0.0` | +| `port` | `Number` | Port of your host. Defaults to `8080` | +| `locations` | `Array` | One or more [application shell](https://developers.google.com/web/fundamentals/architecture/app-shell) locations, e.g. `"/"` and/or `"/profile"` | +| `basePath` | `String` | Root path of your application on the server. This is inserted as an HTTP path prefix between `host` and `locations`. For example, if you set e.g. `"basePath": "my-custom-basepath"` and `"location": ["/profile"]`, then your application would be available at `http://0.0.0.0:8080/my-custom-basepath/profile/` | +| `assetPath` | `String` | HTTP root path of your asset files on the server. It's not dependent on `basePath`, you can define totally separate directories | +| `browsers` | `String` | [Browserslist](https://www.npmjs.com/package/browserslist) query. Defaults to `"> 1%, last 2 versions, Firefox ESR"` (which is also the Browserlist default query). It is used for Babel and PostCSS | +| `node` | `String` | [Node target version](https://www.npmjs.com/package/babel-preset-env#targetsnode). Defaults to `current`. It is used to specify the Node version which Babel should compile for | +| `envVars` | `{ HOPS_MODE: 'dynamic' }` | Environment variables meant to be passed to [`webpack.EnvironmentPlugin`](https://webpack.js.org/plugins/environment-plugin/), i.e. made accessible to your app | +| `moduleDirs` | `Array` | One or more directories that Hops should use for module path resolution. For example, you can specify a directory that holds a yet unpublished Node.js package. It works similar to the [resolve.modulesDirectories](http://webpack.github.io/docs/configuration.html#resolve-modulesdirectories) field in Webpack, i.e. if you specify `moduleDirs: ["my-module-dir"]`, it will look in `./my-module-dir`, `../my-module-dir`, `../../my-module-dir` and so on | +| `appDir` | `String` | Directory of your app. This way, you can put your app to a place other than project root. Defaults to `"."` | +| `buildDir` | `String` | Directory where the build artifacts (i.e. your application/asset files) will be saved to. Defaults to `"build"`. Hops always removes the specified directory before starting a new build | +| `cacheDir` | `String` | Directory where internally used artifacts not meant to be served will be output (e.g. the `manifest.json`/`manifest.js` files generated by Webpack). Defaults to `"node_modules/.cache/hops"` | +| `buildConfig` | `String` | Path to your Webpack build configuration file. Defaults to `undefined` - use this option in your `package.json` to overwrite the default configuration. Read more about it at [hops-build-config](https://github.com/xing/hops/tree/master/packages/build-config#available-options) | +| `developConfig` | `String` | Path to your Webpack development configuration file. Defaults to `undefined` - use this option in your `package.json` to overwrite the default configuration. Read more about it at [hops-build-config](https://github.com/xing/hops/tree/master/packages/build-config#available-options) | +| `nodeConfig` | `String` | Path to your Webpack node/server-side rendering configuration file. Defaults to `undefined` - use this option in your `package.json` to overwrite the default configuration. Read more about it at[hops-build-config](https://github.com/xing/hops/tree/master/packages/build-config#available-options) | +| `manifest` | `String` | The application's `manifest.js` as a string. Defaults to a getter function that returns the content of the automatically generated `manifest.js` | +| `extends` | `String` | Path to a baseline configuration (could be for example a node module or a project-specific file), allowing you join the current configuration with that baseline | +| `enableServerTimings` | `Boolean` | A [timings object](https://github.com/remy/server-timings) is added to `res.locals` in hops extension constructors. The object exposes a start and end function to record [server timings](https://www.w3.org/TR/server-timing/#the-server-timing-header-field). When this setting is set to `false`, the functions can still be called, but they will not record anything. Hops adds internal timings as well. Defaults to `true`. | +| All keys matching `/(config|file|dir)s?$/i` will be treated as a filesystem path (or array thereof) and resolved relative to your app's root folder. This only applies if the respective value is not an absolute path already. | Additionally, you can use placeholders within config properties to reference others. For example, by configuring `"fooDir": "/foo"`, you can specify a subfolder of cache directory. diff --git a/packages/config/index.js b/packages/config/index.js index 16c906454..ea4bf074c 100644 --- a/packages/config/index.js +++ b/packages/config/index.js @@ -31,6 +31,7 @@ function applyDefaultConfig(config) { assetPath: '', workerPath: '/sw.js', workerFile: null, + enableServerTimings: true, browsers: '> 1%, last 2 versions, Firefox ESR', node: 'current', envVars: { HOPS_MODE: 'dynamic' }, diff --git a/packages/express/lib/app.js b/packages/express/lib/app.js index 26062d560..d203f5665 100644 --- a/packages/express/lib/app.js +++ b/packages/express/lib/app.js @@ -15,6 +15,7 @@ var swRe = new RegExp(hopsConfig.workerPath + '$'); function createApp(options) { var app = express(); + app.use(utils.timings); app.use(helmet()); app.use(compression()); app.use(utils.rewritePath); diff --git a/packages/express/lib/utils.js b/packages/express/lib/utils.js index 127a738dc..d9344d8c6 100644 --- a/packages/express/lib/utils.js +++ b/packages/express/lib/utils.js @@ -120,6 +120,13 @@ exports.assetsMiddleware = function assetsMiddleware(req, res, next) { next(); }; +exports.timings = hopsConfig.enableServerTimings + ? require('server-timings') + : function(req, res, next) { + res.locals.timings = { start: function() {}, end: function() {} }; + next(); + }; + exports.bootstrap = hopsConfig.bootstrapServer || function() {}; exports.teardown = hopsConfig.teardownServer || function() {}; diff --git a/packages/express/package.json b/packages/express/package.json index a67499184..4fa190b55 100644 --- a/packages/express/package.json +++ b/packages/express/package.json @@ -26,6 +26,7 @@ "express": "^4.16.0", "helmet": "^3.8.2", "hops-config": "10.2.0-rc.0", - "mime": "^2.2.0" + "mime": "^2.2.0", + "server-timings": "^2.0.1" } } diff --git a/packages/spec/config.js b/packages/spec/config.js index ea86f94c3..d4f07de6c 100644 --- a/packages/spec/config.js +++ b/packages/spec/config.js @@ -35,6 +35,7 @@ describe('config', function() { buildDir: path.resolve('build'), cacheDir: path.resolve(path.join('node_modules', '.cache', 'hops')), workerFile: null, + enableServerTimings: true, workerPath: '/sw.js', }); }); diff --git a/yarn.lock b/yarn.lock index 1f94c6cd8..02f4abb74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5578,7 +5578,7 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" -on-headers@~1.0.1: +on-headers@^1.0.1, on-headers@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" @@ -7223,6 +7223,12 @@ serve-static@1.13.1: parseurl "~1.3.2" send "0.16.1" +server-timings@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/server-timings/-/server-timings-2.0.1.tgz#77b9febc1fab102d1b2c5dc8838767780d0c7c93" + dependencies: + on-headers "^1.0.1" + serverless-http@^1.5.2: version "1.5.3" resolved "https://registry.yarnpkg.com/serverless-http/-/serverless-http-1.5.3.tgz#86b695a354a7780715672291cc5c1f5fc6bcff2e"