Skip to content

Commit 4e84840

Browse files
emilbayesgoto-bus-stop
authored andcommitted
Add base option (#399)
* Add baseHref option * base-href -> base
1 parent b4a0f9c commit 4e84840

File tree

4 files changed

+85
-13
lines changed

4 files changed

+85
-13
lines changed

bin.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ var argv = minimist(process.argv.slice(2), {
5757
alias: {
5858
help: 'h',
5959
quiet: 'q',
60-
version: 'v'
60+
version: 'v',
61+
'base': 'base'
6162
},
6263
boolean: [
6364
'help',

lib/cmd-build.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ module.exports = build
1717
function build (entry, outdir, opts) {
1818
var bankaiOpts = {
1919
logStream: pumpify(pinoColada(), process.stdout),
20-
watch: false
20+
watch: false,
21+
base: opts.base
2122
}
2223
var compiler = bankai(entry, bankaiOpts)
2324
var log = compiler.log

lib/graph-document.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,23 @@ function node (state, createEdge) {
6464
var language = res.language
6565
var title = res.title
6666
var body = res.body
67+
var base = state.metadata.opts.base
6768

6869
var hasDynamicScripts = state.scripts.list.buffer.length > 0
6970

7071
var html = head(body, language)
7172
var d = documentify(entry, html)
7273
var header = [
7374
viewportTag(),
74-
scriptTag({ hash: state.scripts.bundle.hash }),
75+
scriptTag({ hash: state.scripts.bundle.hash, base: base }),
7576
hasDynamicScripts && dynamicScriptsTag({
7677
bundleNames: String(state.scripts.list.buffer).split(','),
77-
scripts: state.scripts
78+
scripts: state.scripts,
79+
base: base
7880
}),
7981
preloadTag(),
80-
loadFontsTag({ fonts: fonts }),
81-
manifestTag(),
82+
loadFontsTag({ fonts: fonts, base: base }),
83+
manifestTag({ base: base }),
8284
descriptionTag({ description: String(state.manifest.description.buffer) }),
8385
themeColorTag({ color: String(state.manifest.color.buffer) }),
8486
titleTag({ title: title })
@@ -98,7 +100,7 @@ function node (state, createEdge) {
98100
d.transform(criticalTransform, { css: state.styles.bundle.buffer })
99101
}
100102

101-
d.transform(addToHead, styleTag({ hash: state.styles.bundle.hash }))
103+
d.transform(addToHead, styleTag({ hash: state.styles.bundle.hash, base: base }))
102104

103105
function complete (buf) { done(null, buf) }
104106

@@ -124,7 +126,7 @@ function preloadTag () {
124126
function scriptTag (opts) {
125127
var hex = opts.hash.toString('hex').slice(0, 16)
126128
var base64 = 'sha512-' + opts.hash.toString('base64')
127-
var link = `/${hex}/bundle.js`
129+
var link = `${opts.base || ''}/${hex}/bundle.js`
128130
return `<script src="${link}" defer integrity="${base64}"></script>`
129131
}
130132

@@ -133,7 +135,7 @@ function dynamicScriptsTag (opts) {
133135
name = name.replace(/\.js$/, '')
134136
var hash = opts.scripts[name].hash
135137
var hex = hash.toString('hex').slice(0, 16)
136-
var link = `/${hex}/${name}.js`
138+
var link = `${opts.base || ''}/${hex}/${name}.js`
137139
return `<link rel="prefetch" href="${link}">`
138140
}).join('')
139141
}
@@ -144,20 +146,20 @@ function dynamicScriptsTag (opts) {
144146
// https://twitter.com/yoshuawuyts/status/920794607314759681
145147
function styleTag (opts) {
146148
var hex = opts.hash.toString('hex').slice(0, 16)
147-
var link = `/${hex}/bundle.css`
149+
var link = `${opts.base || ''}/${hex}/bundle.css`
148150
return `<link rel="preload" as="style" href="${link}" onload="this.rel='stylesheet'">`
149151
}
150152

151153
function loadFontsTag (opts) {
152154
return opts.fonts.reduce(function (html, font) {
153-
if (!path.isAbsolute(font)) font = '/' + font
155+
if (!path.isAbsolute(font)) font = (opts.base || '') + '/' + font
154156
return html + `<link rel="preload" as="font" crossorigin href="${font}">`
155157
}, '')
156158
}
157159

158-
function manifestTag () {
160+
function manifestTag (opts) {
159161
return `
160-
<link rel="manifest" href="/manifest.json">
162+
<link rel="manifest" href="${opts.base || ''}/manifest.json">
161163
`.replace(/\n +/g, '')
162164
}
163165

test/document.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,71 @@ tape('server render choo apps', function (assert) {
141141
})
142142
})
143143
})
144+
145+
tape('server render choo apps with root set', function (assert) {
146+
var expected = `
147+
<!DOCTYPE html>
148+
<html lang="en-US" dir="ltr">
149+
<head>
150+
<meta charset="utf-8">
151+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
152+
<script src="some-custom-root/__SCRIPTS_HASH__/bundle.js" integrity="sha512-__SCRIPTS_INTEGRITY__" defer></script>
153+
<script>;(function(a){"use strict";var b=function(b,c,d){function e(a){return h.body?a():void setTimeout(function(){e(a)})}function f(){i.addEventListener&&i.removeEventListener("load",f),i.media=d||"all"}var g,h=a.document,i=h.createElement("link");if(c)g=c;else{var j=(h.body||h.getElementsByTagName("head")[0]).childNodes;g=j[j.length-1]}var k=h.styleSheets;i.rel="stylesheet",i.href=b,i.media="only x",e(function(){g.parentNode.insertBefore(i,c?g:g.nextSibling)});var l=function(a){for(var b=i.href,c=k.length;c--;)if(k[c].href===b)return a();setTimeout(function(){l(a)})};return i.addEventListener&&i.addEventListener("load",f),i.onloadcssdefined=l,l(f),i};"undefined"!=typeof exports?exports.loadCSS=b:a.loadCSS=b})("undefined"!=typeof global?global:this);;(function(a){if(a.loadCSS){var b=loadCSS.relpreload={};if(b.support=function(){try{return a.document.createElement("link").relList.supports("preload")}catch(b){return!1}},b.poly=function(){for(var b=a.document.getElementsByTagName("link"),c=0;c<b.length;c++){var d=b[c];"preload"===d.rel&&"style"===d.getAttribute("as")&&(a.loadCSS(d.href,d,d.getAttribute("media")),d.rel=null)}},!b.support()){b.poly();var c=a.setInterval(b.poly,300);a.addEventListener&&a.addEventListener("load",function(){b.poly(),a.clearInterval(c)}),a.attachEvent&&a.attachEvent("onload",function(){a.clearInterval(c)})}}})(this);</script>
154+
<link rel="manifest" href="some-custom-root/manifest.json">
155+
<meta name="description" content=>
156+
<meta name="theme-color" content=#fff>
157+
<title></title>
158+
<link rel="preload" as="style" href="some-custom-root/__STYLE_HASH__/bundle.css" onload="this.rel='stylesheet'">
159+
</head>
160+
<body>
161+
meow
162+
</body>
163+
</html>
164+
`.replace(/\n +/g, '')
165+
166+
var script = dedent`
167+
var html = require('choo/html')
168+
var choo = require('choo')
169+
170+
var app = choo()
171+
app.route('/', function () {
172+
return html\`<body>meow</body>\`
173+
})
174+
if (module.parent) module.exports = app
175+
else app.mount('body')
176+
`
177+
178+
var dirname = 'document-pipeline-' + (Math.random() * 1e4).toFixed()
179+
tmpDirname = path.join(__dirname, '../tmp', dirname)
180+
var tmpScriptname = path.join(tmpDirname, 'index.js')
181+
182+
mkdirp.sync(tmpDirname)
183+
fs.writeFileSync(tmpScriptname, script)
184+
185+
var compiler = bankai(tmpScriptname, { watch: false, base: 'some-custom-root' })
186+
compiler.documents('/', function (err, res) {
187+
assert.error(err, 'no error writing document')
188+
assertHtml(assert, String(res.buffer), expected)
189+
})
190+
191+
compiler.on('change', function (nodeName, second) {
192+
if (nodeName !== 'documents' || second !== 'list') return
193+
assert.end()
194+
})
195+
196+
compiler.on('error', function () {
197+
// assert.error(err, 'no error')
198+
})
199+
200+
compiler.scripts('bundle.js', function (err, res) {
201+
assert.ifError(err, 'no err bundling scripts')
202+
expected = expected.replace('__SCRIPTS_HASH__', res.hash.toString('hex').slice(0, 16))
203+
expected = expected.replace('__SCRIPTS_INTEGRITY__', res.hash.toString('base64'))
204+
compiler.styles('bundle.css', function (err, res) {
205+
assert.ifError(err, 'no err bundling style')
206+
assert.ifError(err)
207+
expected = expected.replace('__STYLE_HASH__', res.hash.toString('hex').slice(0, 16))
208+
expected = expected.replace('__STYLE_INTEGRITY__', res.hash.toString('base64'))
209+
})
210+
})
211+
})

0 commit comments

Comments
 (0)