diff --git a/package-lock.json b/package-lock.json index ad4941a25..03c663bc1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4690,6 +4690,11 @@ } } }, + "rollup-dependency-tree": { + "version": "git+https://github.com/benmccann/rollup-dependency-tree.git#5815db6771fecaae7c84372da6e590474c32e953", + "from": "git+https://github.com/benmccann/rollup-dependency-tree.git", + "dev": true + }, "rollup-plugin-commonjs": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.0.1.tgz", diff --git a/package.json b/package.json index 31e13d475..4df13cec5 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "puppeteer": "^3.3.0", "require-relative": "^0.8.7", "rollup": "^1.17.0", + "rollup-dependency-tree": "https://github.com/benmccann/rollup-dependency-tree.git", "rollup-plugin-commonjs": "^10.0.1", "rollup-plugin-json": "^4.0.0", "rollup-plugin-node-resolve": "^5.2.0", @@ -66,7 +67,7 @@ "test": "mocha --opts mocha.opts", "pretest": "npm run build", "build": "rm -rf dist && rollup -c", - "prepare": "npm run build", + "prepare": "cd ./node_modules/rollup-dependency-tree && npm install && npm run build", "dev": "rollup -cw", "prepublishOnly": "npm test" }, diff --git a/runtime/src/server/middleware/get_page_handler.ts b/runtime/src/server/middleware/get_page_handler.ts index c39e96c0c..a1f0bc053 100644 --- a/runtime/src/server/middleware/get_page_handler.ts +++ b/runtime/src/server/middleware/get_page_handler.ts @@ -50,44 +50,56 @@ export function get_page_handler( bundler: 'rollup' | 'webpack', shimport: string | null, assets: Record, + dependencies: Record, + css: { + main: string | null, + chunks: Record + }, legacy_assets?: Record - } = get_build_info(); + } = get_build_info(); res.setHeader('Content-Type', 'text/html'); res.setHeader('Cache-Control', dev ? 'no-cache' : 'max-age=600'); // preload main.js and current route - // TODO detect other stuff we can preload? images, CSS, fonts? - let preloaded_chunks = Array.isArray(build_info.assets.main) ? build_info.assets.main : [build_info.assets.main]; + // TODO detect other stuff we can preload like fonts? + let preload_files = Array.isArray(build_info.assets.main) ? build_info.assets.main : [build_info.assets.main]; if (!error && !is_service_worker_index) { page.parts.forEach(part => { if (!part) return; // using concat because it could be a string or an array. thanks webpack! - preloaded_chunks = preloaded_chunks.concat(build_info.assets[part.name]); + preload_files = preload_files.concat(build_info.assets[part.name]); }); } + let es6_preload = false; if (build_info.bundler === 'rollup') { - // TODO add dependencies and CSS - const link = preloaded_chunks - .filter(file => file && !file.match(/\.map$/)) - .map(file => `<${req.baseUrl}/client/${file}>;rel="modulepreload"`) - .join(', '); - - res.setHeader('Link', link); - } else { - const link = preloaded_chunks - .filter(file => file && !file.match(/\.map$/)) - .map((file) => { - const as = /\.css$/.test(file) ? 'style' : 'script'; - return `<${req.baseUrl}/client/${file}>;rel="preload";as="${as}"`; - }) - .join(', '); - - res.setHeader('Link', link); + + es6_preload = true; + + const route = page.parts[page.parts.length - 1].file; + + // JS + preload_files = preload_files.concat(build_info.dependencies[route]); + + // CSS + preload_files = preload_files.concat(build_info.css.main); + preload_files = preload_files.concat(build_info.css.chunks[route]); } + const link = preload_files + .filter((v, i, a) => a.indexOf(v) === i) // remove any duplicates + .filter(file => file && !file.match(/\.map$/)) // exclude source maps + .map((file) => { + const as = /\.css$/.test(file) ? 'style' : 'script'; + const rel = es6_preload && as === 'script' ? 'modulepreload' : 'preload'; + return `<${req.baseUrl}/client/${file}>;rel="${rel}";as="${as}"`; + }) + .join(', '); + + res.setHeader('Link', link); + let session; try { session = await session_getter(req, res); diff --git a/src/core/create_compilers/RollupResult.ts b/src/core/create_compilers/RollupResult.ts index 99ea2a51f..eda310693 100644 --- a/src/core/create_compilers/RollupResult.ts +++ b/src/core/create_compilers/RollupResult.ts @@ -1,6 +1,7 @@ import * as path from 'path'; import colors from 'kleur'; import pb from 'pretty-bytes'; +import transitiveDeps from 'rollup-dependency-tree'; import RollupCompiler from './RollupCompiler'; import extract_css from './extract_css'; import { left_pad } from '../../utils'; @@ -13,6 +14,7 @@ export default class RollupResult implements CompileResult { warnings: CompileError[]; chunks: Chunk[]; assets: Record; + dependencies: Record; css_files: CssFile[]; css: { main: string, @@ -36,8 +38,6 @@ export default class RollupResult implements CompileResult { this.css_files = compiler.css_files; - // TODO populate this properly. We don't have named chunks, as in - // webpack, but we can have a route -> [chunk] map or something this.assets = {}; if (typeof compiler.input === 'string') { @@ -54,6 +54,8 @@ export default class RollupResult implements CompileResult { } } + this.dependencies = transitiveDeps(compiler.chunks); + this.summary = compiler.chunks.map(chunk => { const size_color = chunk.code.length > 150000 ? colors.bold().red : chunk.code.length > 50000 ? colors.bold().yellow : colors.bold().white; const size_label = left_pad(pb(chunk.code.length), 10); @@ -89,12 +91,18 @@ export default class RollupResult implements CompileResult { } to_json(manifest_data: ManifestData, dirs: Dirs): BuildInfo { - // TODO extract_css has side-effects that don't belong - // in a method called to_json + const dependencies = {}; + Object.entries(this.dependencies).forEach(([key, value]) => { + dependencies[path.relative(dirs.routes, key)] = value; + }); + return { bundler: 'rollup', shimport: require('shimport/package.json').version, assets: this.assets, + dependencies, + + // TODO extract_css has side-effects that don't belong in a method called to_json css: extract_css(this, manifest_data.components, dirs, this.sourcemap) }; } diff --git a/src/core/create_compilers/interfaces.ts b/src/core/create_compilers/interfaces.ts index 11b8b0e23..69e4bf39f 100644 --- a/src/core/create_compilers/interfaces.ts +++ b/src/core/create_compilers/interfaces.ts @@ -31,9 +31,10 @@ export type BuildInfo = { bundler: string; shimport: string; assets: Record; + dependencies: Record; legacy_assets?: Record; css: { main: string | null, chunks: Record } -} \ No newline at end of file +}