Skip to content

Commit

Permalink
Refactor to sirv
Browse files Browse the repository at this point in the history
Use prettier

Resolve #42 as sirv supports Range
  • Loading branch information
thgh committed Nov 10, 2019
1 parent 0e17e03 commit d2f0731
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 1,470 deletions.
23 changes: 17 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"scripts": {
"build": "rollup -c",
"dev": "rollup -cw",
"lint": "standard --fix rollup.config.js src/**",
"lint": "prettier --write rollup.config.js src/**",
"prepare": "yarn lint && yarn build",
"test": "cd test && rollup -c || cd .."
},
Expand All @@ -32,13 +32,24 @@
"files": [
"dist"
],
"dependencies": {
"mime": ">=2.0.3",
"opener": "1"
},
"devDependencies": {
"connect-compose": "0.0.1",
"opener": "1",
"prettier": "^1.19.1",
"rollup": "1",
"rollup-plugin-buble": "^0.15.0",
"standard": "14"
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0",
"sirv": "^0.4.2"
},
"prettier": {
"trailingComma": "none",
"semi": false,
"singleQuote": true
},
"husky": {
"hooks": {
"pre-commit": "pretty-quick --pattern \"**/*.(js|html)\" --staged"
}
}
}
12 changes: 6 additions & 6 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import buble from 'rollup-plugin-buble'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'

export default {
input: 'src/index.js',
output: [
{ file: 'dist/index.cjs.js', format: 'cjs' },
{ file: 'dist/index.es.js', format: 'esm' }
],
plugins: [buble()],
onwarn ({ code, message }) {
if (code !== 'UNRESOLVED_IMPORT') {
console.warn(message)
}
}
plugins: [commonjs(), resolve(), buble()],
external: [].concat(
require('module').builtinModules || Object.keys(process.binding('natives'))
)
}
142 changes: 66 additions & 76 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,87 +1,95 @@
import { readFile } from 'fs'
import { createServer as createHttpsServer } from 'https'
import { createServer } from 'http'
import { resolve } from 'path'

import mime from 'mime'
import opener from 'opener'
import sirv from 'sirv'
import compose from 'connect-compose'

let server

/**
* Serve your rolled up bundle like webpack-dev-server
* @param {ServeOptions|string|string[]} options
*/
function serve (options = { contentBase: '' }) {
export default function serve(options = { contentBase: '' }) {
if (Array.isArray(options) || typeof options === 'string') {
options = { contentBase: options }
}
options.contentBase = Array.isArray(options.contentBase) ? options.contentBase : [options.contentBase || '']
options.contentBase = Array.isArray(options.contentBase)
? options.contentBase
: [options.contentBase || '']
options.port = options.port || 10001
options.headers = options.headers || {}
options.https = options.https || false
options.openPage = options.openPage || ''
mime.default_type = 'text/plain'

const requestListener = (request, response) => {
// Remove querystring
const urlPath = decodeURI(request.url.split('?')[0])

Object.keys(options.headers).forEach((key) => {
response.setHeader(key, options.headers[key])
})

readFileFromContentBase(options.contentBase, urlPath, function (error, content, filePath) {
if (!error) {
return found(response, filePath, content)
}
if (error.code !== 'ENOENT') {
response.writeHead(500)
response.end('500 Internal Server Error' +
'\n\n' + filePath +
'\n\n' + Object.values(error).join('\n') +
'\n\n(rollup-plugin-serve)', 'utf-8')
return
}
if (options.historyApiFallback) {
const fallbackPath = typeof options.historyApiFallback === 'string' ? options.historyApiFallback : '/index.html'
readFileFromContentBase(options.contentBase, fallbackPath, function (error, content, filePath) {
if (error) {
notFound(response, filePath)
} else {
found(response, filePath, content)
}
})
} else {
notFound(response, filePath)
}
})
}

// release previous server instance if rollup is reloading configuration in watch mode
// Release previous server instance if rollup is reloading configuration in watch mode
if (server) {
server.close()
} else {
closeServerOnTermination()
}

// Serve all folders
const middlewares = options.contentBase.map(base => sirv(base, { dev: true }))

// Send custom headers
if (options.headers) {
middlewares.unshift(setHeaders)
}

// Fallback to another page
let { historyApiFallback: fallback } = options
if (fallback) {
// Defaults to index.html, sirv know where to look
fallback = typeof fallback === 'string' ? fallback : '/'

// Must start with /
fallback = (fallback.startsWith('/') ? '' : '/') + fallback

// Swap out the requested page with the fallback page
middlewares.push((req, res, next) => {
req.originalUrl = req.url
req.url = fallback
next()
})

// Serve the static files again, this time looking for the fallback page
const serveStatic = middlewares.slice(-3, -1)
serveStatic.forEach(middleware => middlewares.push(middleware))
}

middlewares.push(errorPage)

// Combine all middlewares into one
const app = compose(middlewares)

// If HTTPS options are available, create an HTTPS server
if (options.https) {
server = createHttpsServer(options.https, requestListener).listen(options.port, options.host)
server = createHttpsServer(options.https, app).listen(
options.port,
options.host
)
} else {
server = createServer(requestListener).listen(options.port, options.host)
server = createServer(app).listen(options.port, options.host)
}

let running = options.verbose === false

return {
name: 'serve',
generateBundle () {
generateBundle() {
if (!running) {
running = true

// Log which url to visit
const url = (options.https ? 'https' : 'http') + '://' + (options.host || 'localhost') + ':' + options.port
const url =
(options.https ? 'https' : 'http') +
'://' +
(options.host || 'localhost') +
':' +
options.port
options.contentBase.forEach(base => {
console.log(green(url) + ' -> ' + resolve(base))
})
Expand All @@ -97,40 +105,24 @@ function serve (options = { contentBase: '' }) {
}
}
}
}

function readFileFromContentBase (contentBase, urlPath, callback) {
let filePath = resolve(contentBase[0] || '.', '.' + urlPath)

// Load index.html in directories
if (urlPath.endsWith('/')) {
filePath = resolve(filePath, 'index.html')
function setHeaders(req, res, next) {
Object.keys(options.headers).forEach(key => {
res.setHeader(key, options.headers[key])
})
next()
}

readFile(filePath, (error, content) => {
if (error && contentBase.length > 1) {
// Try to read from next contentBase
readFileFromContentBase(contentBase.slice(1), urlPath, callback)
} else {
// We know enough
callback(error, content, filePath)
}
})
}

function notFound (response, filePath) {
response.writeHead(404)
response.end('404 Not Found' +
'\n\n' + filePath +
'\n\n(rollup-plugin-serve)', 'utf-8')
}

function found (response, filePath, content) {
response.writeHead(200, { 'Content-Type': mime.getType(filePath) })
response.end(content, 'utf-8')
function errorPage(req, res) {
res.writeHead(404)
res.end(
'404 Not Found' + '\n\n' + req.originalUrl + '\n\n(rollup-plugin-serve)',
'utf-8'
)
}
}

function green (text) {
function green(text) {
return '\u001b[1m\u001b[32m' + text + '\u001b[39m\u001b[22m'
}

Expand All @@ -146,8 +138,6 @@ function closeServerOnTermination() {
})
}

export default serve

/**
* @typedef {Object} ServeOptions
* @property {boolean} [open=false] Launch in browser (default: `false`)
Expand Down
2 changes: 1 addition & 1 deletion test/rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import serve from '..'
import serve from '../dist/index.es'

export default {
input: 'entry.js',
Expand Down

0 comments on commit d2f0731

Please sign in to comment.