diff --git a/http.js b/http.js
index 7a357349..79d493cd 100644
--- a/http.js
+++ b/http.js
@@ -36,6 +36,11 @@ function start (entry, opts) {
if (name === 'styles:bundle') emitter.emit('styles:bundle', node)
})
+ router.route(/^\/(favicon\.)(ico|png|gif)$/, function (req, res, params) {
+ var filename = params[1] + params[2]
+ pump(send(req, filename), res)
+ })
+
router.route(/^\/manifest\.json$/, function (req, res, params) {
compiler.manifest(function (err, node) {
if (err) {
diff --git a/index.js b/index.js
index daf8e9d8..816f1587 100644
--- a/index.js
+++ b/index.js
@@ -12,6 +12,7 @@ var ServerRender = require('./ssr')
var assetsNode = require('./lib/graph-assets')
var documentNode = require('./lib/graph-document')
+var faviconNode = require('./lib/graph-favicon')
var manifestNode = require('./lib/graph-manifest')
var reloadNode = require('./lib/graph-reload')
var scriptNode = require('./lib/graph-script')
@@ -100,12 +101,13 @@ function Bankai (entry, opts) {
})
// Insert nodes into the graph.
- var documentDependencies = [ 'assets:list', 'manifest:bundle', 'styles:bundle', 'scripts:bundle' ]
+ var documentDependencies = [ 'assets:list', 'manifest:bundle', 'styles:bundle', 'scripts:bundle', 'favicon:bundle' ]
if (opts.reload) {
documentDependencies.push('reload:bundle')
this.graph.node('reload', reloadNode)
}
+ this.graph.node('favicon', faviconNode)
this.graph.node('assets', assetsNode)
this.graph.node('documents', documentDependencies, documentNode)
this.graph.node('manifest', manifestNode)
diff --git a/lib/cmd-build.js b/lib/cmd-build.js
index 28cd879c..0b31aaa0 100644
--- a/lib/cmd-build.js
+++ b/lib/cmd-build.js
@@ -50,6 +50,7 @@ function build (entry, outdir, opts) {
var stepName = nodeName + ':' + edgeName
if (stepName === 'assets:list') writeAssets('assets')
if (stepName === 'documents:list') writeDocuments('documents')
+ if (stepName === 'favicon:bundle') writeFavicon()
if (stepName === 'scripts:bundle') writeScripts('scripts')
if (stepName === 'service-worker:bundle') {
var filename = compiler.graph.metadata.serviceWorker
@@ -76,32 +77,27 @@ function build (entry, outdir, opts) {
var dirname = utils.dirname(dest)
if (dirname === dest) {
- copy(done)
+ copy(src, dest, compiler.dirname, done)
} else {
mkdirp(dirname, function (err) {
if (err) return done(err)
- copy(done)
+ copy(src, dest, compiler.dirname, done)
})
}
+ }
+ }
- // Node <= 8.x does not have fs.copyFile(). This API is cool because
- // on some OSes it is zero-copy all the way; e.g. never leaves the
- // kernel! :D
- function copy (done) {
- fsCompare.mtime(src, dest, function (err, diff) {
- if (err) return done(err)
- if (diff === 1) {
- if (fs.copyFile) fs.copyFile(src, dest, fin)
- else pump(fs.createReadStream(src), fs.createWriteStream(dest), fin)
- }
- })
- function fin (err) {
- if (err) return done(err)
- created(compiler.dirname, dest)
- done()
- }
- }
+ function writeFavicon () {
+ var favicon = compiler.graph.data.favicon.bundle.buffer.toString()
+ if (favicon.length === 0) {
+ return
}
+ var src = path.join(compiler.dirname, favicon)
+ var dest = path.join(outdir, favicon)
+ copy(src, dest, compiler.dirname, function (err) {
+ if (err) return log.error(err)
+ completed('favicon')
+ })
}
function writeScripts (step) {
@@ -182,6 +178,24 @@ function build (entry, outdir, opts) {
}
}
+ // Node <= 8.x does not have fs.copyFile(). This API is cool because
+ // on some OSes it is zero-copy all the way; e.g. never leaves the
+ // kernel! :D
+ function copy (src, dest, dirname, done) {
+ fsCompare.mtime(src, dest, function (err, diff) {
+ if (err) return done(err)
+ if (diff === 1) {
+ if (fs.copyFile) fs.copyFile(src, dest, fin)
+ else pump(fs.createReadStream(src), fs.createWriteStream(dest), fin)
+ }
+ })
+ function fin (err) {
+ if (err) return done(err)
+ created(dirname, dest)
+ done()
+ }
+ }
+
function created (basedir, filename) {
var relative = path.relative(process.cwd(), filename)
log.info(`${clr('created', 'magenta')}: ${relative}`)
diff --git a/lib/graph-document.js b/lib/graph-document.js
index d81cbd91..d064cbf6 100644
--- a/lib/graph-document.js
+++ b/lib/graph-document.js
@@ -108,6 +108,7 @@ function node (state, createEdge) {
}),
preloadTag(),
loadFontsTag({ fonts: fonts, base: base }),
+ faviconsTag({ favicon: state.favicon.bundle.buffer }),
manifestTag({ base: base }),
descriptionTag({ description: state.manifest.bundle.description }),
themeColorTag({ color: state.manifest.bundle.color }),
@@ -197,6 +198,14 @@ function manifestTag (opts) {
`.replace(/\n +/g, '')
}
+function faviconsTag (opts) {
+ var favicon = opts.favicon.toString()
+ if (favicon.length > 0) {
+ return ``
+ }
+ return ``
+}
+
function viewportTag () {
return `
diff --git a/lib/graph-favicon.js b/lib/graph-favicon.js
new file mode 100644
index 00000000..56f0a255
--- /dev/null
+++ b/lib/graph-favicon.js
@@ -0,0 +1,22 @@
+var path = require('path')
+var utils = require('./utils')
+
+module.exports = node
+
+function node (state, createEdge) {
+ var dirname = state.metadata.dirname
+ var filenames = [
+ 'favicon.ico',
+ 'favicon.png',
+ 'favicon.gif'
+ ]
+
+ // find favicon at the root
+ utils.find(dirname, filenames, function (err, filename) {
+ if (err || filename === void 0) {
+ createEdge('bundle', Buffer.from(''))
+ return
+ }
+ createEdge('bundle', Buffer.from(path.relative(dirname, filename)))
+ })
+}