This commit is contained in:
2022-07-21 03:28:35 +00:00
parent d7c883d6df
commit 51b34b0e1d
30103 changed files with 4152204 additions and 23 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 - Nuxt.js Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+149
View File
@@ -0,0 +1,149 @@
# ♡ serve-placeholder
> Connect/Express middleware to respond with better placeholders based on request instead of 404 page
[![Standard JS][standard-src]][standard-href]
[![david dm][david-src]][david-href]
[![codecov][codecov-src]][codecov-href]
[![circleci][circleci-src]][circleci-href]
[![npm version][npm-v-src]][npm-v-href]
[![npm downloads][npm-dt-src]][npm-dt-href]
[![package phobia][packagephobia-src]][packagephobia-href]
## Why?
**💵 Rendering 404 errors is costly**
- Each 404 error for assets means a new SSR request that adds extra loads to the server and increases crash chances.
**👌 Graceful Responses**
- Sometimes, we can send better responses alongside with 404 code instead of nothing. For example, for images, we send a fallback transparent 1x1 image.
**🔍 SEO Friendly**
- Don't allow indexing invalid URLs with ugly html pages.
- Remove extra SSR loads when assets like `robots.txt` or `favicon.ico` doesn't exist.
## Usage
Install package:
```bash
npm install serve-placeholder
```
OR
```bash
yarn add serve-placeholder
```
Import and use middleware:
```js
const placeholder = require('serve-placeholder')
// import placeholder from 'serve-placeholder'
// [regular middleware such as serve-static]
// Response with appreciate placeholders
app.use(placeholder())
//app.use(placeholder({ /* options */ }))
// [global error handler]
```
## Options
### `handlers`
A mapping from file extensions to the handler. Extensions should start with *dot* like `.js`.
You can disable any of the handlers by setting the value to `null`
If the value of a handler is set to `false`, middleware will be ignored for that extension.
### `statusCode`
- Default: `404`
Sets `statusCode` for all handled responses. Set to `false` to disable overriding statusCode.
### `skipUnknown`
- Default: `false`
Skip middleware when no handler is defined for the current request.
Please note that if this option is set to `true`, then `default` handler will be disabled!
### `placeholders`
- Type: `Object`
A mapping from handler to placeholder. Values can be `String` or `Buffer`. You can disable any of the placeholders by setting the value to `false`.
### `mimes`
- Type: `Object`
A mapping from handler to the mime type. Mime type will be set as `Content-Type` header. You can disable sending any of the mimes by setting the value to `false`.
### `noCache`
- Default: `true`
Set headers to prevent accidentally caching 404 resources.
When enabled, these headers will be sent:
```js
{
'cache-control': 'no-cache, no-store, must-revalidate',
'expires': '0',
'pragma': 'no-cache'
}
```
## Defaults
These are [default handlers](./src/defaults.js). You can override every of them using provided options.
Handler | Extensions | Mime type | Placeholder
-----------|------------------------|--------------------------|-------------------
`default` | any unknown extension | - | -
`css` | `.css` | `text/css` | `/* style not found */`
`html` | `.html`, `.htm` | `text/html` | `<!-- page not found -->`
`js` | `.js` | `application/javascript` | `/* script not found */`
`json` | `.json` | `application/json` | `{}`
`map` | `.map` | `application/json` | [empty sourcemap v3 json]
`plain` | `.txt`, `.text`, `.md` | `text/plain` | [empty]
`image` | `.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`, `.webp`, `.bmp`, `.ico` | `image/gif` | [transparent 1x1 image]
## License
MIT. Made with 💖 by [Nuxt.js](https://nuxtjs.org) team!
<!-- Refs -->
[standard-src]: https://flat.badgen.net/badge/code%20style/standard/green
[standard-href]: https://standardjs.com
[npm-v-src]: https://flat.badgen.net/npm/v/serve-placeholder/latest
[npm-v-href]: https://npmjs.com/package/serve-placeholder
[npm-dt-src]: https://flat.badgen.net/npm/dt/serve-placeholder
[npm-dt-href]: https://npmjs.com/package/serve-placeholder
[packagephobia-src]: https://flat.badgen.net/packagephobia/install/serve-placeholder
[packagephobia-href]: https://packagephobia.now.sh/result?p=serve-placeholder
[david-src]: https://flat.badgen.net/david/dep/nuxt/serve-placeholder
[david-href]: https://david-dm.org/nuxt/serve-placeholder
[codecov-src]: https://flat.badgen.net/codecov/c/github/nuxt/serve-placeholder/master
[codecov-href]: https://codecov.io/gh/nuxt/serve-placeholder
[circleci-src]: https://flat.badgen.net/circleci/github/nuxt/serve-placeholder/master
[circleci-href]: https://circleci.com/gh/nuxt/serve-placeholder
+73
View File
@@ -0,0 +1,73 @@
{
"_args": [
[
"serve-placeholder@1.2.4",
"/home/node/nuxt"
]
],
"_from": "serve-placeholder@1.2.4",
"_id": "serve-placeholder@1.2.4",
"_inBundle": false,
"_integrity": "sha512-jWD9cZXLcr4vHTTL5KEPIUBUYyOWN/z6v/tn0l6XxFhi9iqV3Fc5Y1aFeduUyz+cx8sALzGCUczkPfeOlrq9jg==",
"_location": "/serve-placeholder",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "serve-placeholder@1.2.4",
"name": "serve-placeholder",
"escapedName": "serve-placeholder",
"rawSpec": "1.2.4",
"saveSpec": null,
"fetchSpec": "1.2.4"
},
"_requiredBy": [
"/@nuxt/server"
],
"_resolved": "https://registry.npmjs.org/serve-placeholder/-/serve-placeholder-1.2.4.tgz",
"_spec": "1.2.4",
"_where": "/home/node/nuxt",
"bugs": {
"url": "https://github.com/nuxt/serve-placeholder/issues"
},
"contributes": [
"Pooya Parsa <pooya@pi0.ir>"
],
"dependencies": {
"defu": "^5.0.0"
},
"description": "Connect/Express middleware to respond with better placeholders based on request instead of 404 page",
"devDependencies": {
"axios": "latest",
"codecov": "latest",
"connect": "latest",
"eslint": "latest",
"eslint-config-standard": "latest",
"eslint-plugin-import": "latest",
"eslint-plugin-jest": "latest",
"eslint-plugin-node": "latest",
"eslint-plugin-promise": "latest",
"eslint-plugin-standard": "latest",
"jest": "latest",
"standard-version": "latest"
},
"files": [
"src"
],
"homepage": "https://github.com/nuxt/serve-placeholder#readme",
"license": "MIT",
"main": "src/index.js",
"name": "serve-placeholder",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/nuxt/serve-placeholder.git"
},
"scripts": {
"jest": "jest",
"lint": "eslint src",
"prepare": "npm run test",
"release": "standard-version && git push --follow-tags && npm publish",
"test": "npm run lint && npm run jest"
},
"version": "1.2.4"
}
+58
View File
@@ -0,0 +1,58 @@
const EMPTY_GIF = Buffer.from('R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==', 'base64')
module.exports = {
statusCode: 404,
skipUnknown: false,
noCache: true,
handlers: {
// css
'.css': 'css',
// html
'.html': 'html',
'.htm': 'html',
// image
'.png': 'image',
'.jpg': 'image',
'.jpeg': 'image',
'.gif': 'image',
'.svg': 'image',
'.webp': 'image',
'.bmp': 'image',
'.ico': 'image',
// js
'.js': 'js',
// json
'.json': 'json',
// map
'.map': 'map',
// plain
'.txt': 'plain',
'.text': 'plain',
'.md': 'plain'
},
placeholders: {
css: '/* style not found */',
default: undefined,
html: '<!-- page not found -->',
image: EMPTY_GIF,
js: '/* script not found */',
json: '{}',
map: '{"version": "3", "sources": [], "mappings": "" }',
plain: ''
},
mimes: {
css: 'text/css',
default: undefined,
html: 'text/html',
js: 'application/javascript',
json: 'application/json',
image: 'image/gif',
map: 'application/json',
plain: 'text/plain'
}
}
+64
View File
@@ -0,0 +1,64 @@
const path = require('path')
const defu = require('defu')
const defaults = require('./defaults')
module.exports = function createServePlaceholder (_options) {
// Assign default options
const options = defu(_options, defaults)
return function servePlaceholderMiddleware (req, res, next) {
// If response already sent, skip
if (res.writableEnded) {
return
}
// Get url from req object
const url = req.url.split('?')[0]
// Get ext of requst url
const ext = path.extname(url)
// Try to find a handler based on ext
let handler = options.handlers[ext]
// Skip middleware is handler is explictly set to false
if (handler === false) {
return next()
}
// In case of no handler guessed
if (typeof handler === 'undefined') {
if (options.skipUnknown) {
// Skip this middleware
return next()
} else {
// Use 'default' handler
handler = 'default'
}
}
// Set statusCode
if (options.statusCode) {
res.statusCode = options.statusCode
}
// Try to set appreciate mime type based on handler
const mime = options.mimes[handler]
if (mime) {
res.setHeader('Content-Type', mime)
}
// Prevent caching
if (options.noCache) {
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate') // HTTP 1.1
res.setHeader('Pragma', 'no-cache') // HTTP 1.0
res.setHeader('Expires', '0') // Proxies
}
// Try to find placeholder based on handler
const placeholder = options.placeholders[handler]
// Send placeholder and end response
res.end(placeholder)
}
}