diff --git a/package-lock.json b/package-lock.json index 858914d..3a588fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "sapper", - "version": "0.18.3", + "version": "0.18.5", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -55,9 +55,9 @@ "dev": true }, "@types/node": { - "version": "10.9.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.9.3.tgz", - "integrity": "sha512-DOzWZKUnmFYG0KUOs+9HEBju2QhBU6oM2zeluunQNt0vnJvnkHvtDNlQPZDkTrkC5pZrNx1TPqeL137zciXZMQ==", + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.9.4.tgz", + "integrity": "sha512-fCHV45gS+m3hH17zgkgADUSi2RR1Vht6wOZ0jyHP8rjiQra9f+mIcgwPQHllmDocYOstIEbKlxbFDYlgrTPYqw==", "dev": true }, "@types/rimraf": { @@ -1154,7 +1154,7 @@ }, "buffer": { "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { @@ -1594,7 +1594,7 @@ }, "compare-versions": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-2.0.1.tgz", + "resolved": "http://registry.npmjs.org/compare-versions/-/compare-versions-2.0.1.tgz", "integrity": "sha1-Htwfk2h/2XoyXFn1XkWgfbEGrKY=", "dev": true }, @@ -2071,9 +2071,9 @@ }, "dependencies": { "@types/node": { - "version": "8.10.28", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.28.tgz", - "integrity": "sha512-iHsAzDg3OLH7JP+wipniUULHoDSWLgEDYOvsar6/mpAkTJd9/n23Ap8ikruMlvRTqMv/LXrflH9v/AfiEqaBGg==", + "version": "8.10.29", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.29.tgz", + "integrity": "sha512-zbteaWZ2mdduacm0byELwtRyhYE40aK+pAanQk415gr1eRuu67x7QGOLmn8jz5zI8LDK7d0WI/oT6r5Trz4rzQ==", "dev": true } } @@ -2097,7 +2097,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -2538,7 +2538,7 @@ }, "external-editor": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", "dev": true, "requires": { @@ -4270,9 +4270,9 @@ } }, "make-error": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", - "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", "dev": true }, "mamacro": { @@ -4397,7 +4397,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -4537,7 +4537,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, @@ -4991,7 +4991,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -5682,7 +5682,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -6287,9 +6287,9 @@ } }, "shimport": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/shimport/-/shimport-0.0.9.tgz", - "integrity": "sha512-y0DHz5ffBuz+iXUQgkqjT3yJRuegeyhHeDdqVdDMVDCeuS0Ex6AFPLFNV228EfPQmkDumraLsN9HBcT1qyLxHw==" + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/shimport/-/shimport-0.0.10.tgz", + "integrity": "sha512-3xPFDLmcLj87sx0OwA60qbloMQUsu6VGF97IG4RqxTf91sGeiaaXOPxM1PoQHbaTm4TOhH8zosokqLAZtuNGnA==" }, "signal-exit": { "version": "3.0.2", @@ -7009,7 +7009,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -7074,9 +7074,9 @@ "dev": true }, "uglify-js": { - "version": "3.4.8", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.8.tgz", - "integrity": "sha512-WatYTD84gP/867bELqI2F/2xC9PQBETn/L+7RGq9MQOA/7yFBNvY1UwXqvtILeE6n0ITwBXxp34M0/o70dzj6A==", + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", "requires": { "commander": "~2.17.1", "source-map": "~0.6.1" diff --git a/package.json b/package.json index dcf85fe..7aa8a88 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ }, "dependencies": { "html-minifier": "^3.5.16", - "shimport": "^0.0.9", + "shimport": "^0.0.10", "source-map-support": "^0.5.6", "tslib": "^1.9.1" }, diff --git a/src/api/build.ts b/src/api/build.ts index 5fa9e6a..06ed54a 100644 --- a/src/api/build.ts +++ b/src/api/build.ts @@ -5,9 +5,7 @@ import rimraf from 'rimraf'; import { EventEmitter } from 'events'; import minify_html from './utils/minify_html'; import { create_compilers, create_main_manifests, create_routes, create_serviceworker_manifest } from '../core'; -import { Compilers, Compiler } from '../core/create_compilers'; import * as events from './interfaces'; -import validate_bundler from '../cli/utils/validate_bundler'; import { copy_shimport } from './utils/copy_shimport'; export function build(opts: {}) { @@ -30,6 +28,7 @@ export function build(opts: {}) { async function execute(emitter: EventEmitter, { dest = 'build', app = 'app', + legacy, bundler, webpack = 'webpack', rollup = 'rollup', @@ -57,7 +56,7 @@ async function execute(emitter: EventEmitter, { // create app/manifest/client.js and app/manifest/server.js create_main_manifests({ bundler, routes: route_objects }); - const { client, server, serviceworker } = create_compilers(validate_bundler(bundler), { webpack, rollup }); + const { client, server, serviceworker } = create_compilers(bundler, { webpack, rollup }); const client_result = await client.compile(); emitter.emit('build', { @@ -66,11 +65,34 @@ async function execute(emitter: EventEmitter, { result: client_result }); - fs.writeFileSync(path.join(dest, 'build.json'), JSON.stringify({ + const build_info: { + bundler: string; + shimport: string; + assets: Record; + legacy_assets?: Record; + } = { bundler, shimport: bundler === 'rollup' && require('shimport/package.json').version, assets: client_result.assets - })); + }; + + if (legacy) { + process.env.SAPPER_LEGACY_BUILD = 'true'; + const { client } = create_compilers(bundler, { webpack, rollup }); + + const client_result = await client.compile(); + + emitter.emit('build', { + type: 'client (legacy)', + // TODO duration/warnings + result: client_result + }); + + build_info.legacy_assets = client_result.assets; + delete process.env.SAPPER_LEGACY_BUILD; + } + + fs.writeFileSync(path.join(dest, 'build.json'), JSON.stringify(build_info)); const server_stats = await server.compile(); emitter.emit('build', { diff --git a/src/cli.ts b/src/cli.ts index 41a208e..96cd811 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -31,8 +31,13 @@ prog.command('build [dest]') .describe('Create a production-ready version of your app') .option('-p, --port', 'Default of process.env.PORT', '3000') .option('--bundler', 'Specify a bundler (rollup or webpack, blank for auto)') + .option('--legacy', 'Create separate legacy build') .example(`build custom-dir -p 4567`) - .action(async (dest = 'build', opts: { port: string, bundler?: string }) => { + .action(async (dest = 'build', opts: { + port: string, + legacy: boolean, + bundler?: string + }) => { console.log(`> Building...`); process.env.NODE_ENV = process.env.NODE_ENV || 'production'; @@ -78,9 +83,11 @@ prog.command('export [dest]') .option('--build-dir', 'Specify a custom temporary build directory', '.sapper/prod') .option('--basepath', 'Specify a base path') .option('--timeout', 'Milliseconds to wait for a page (--no-timeout to disable)', 5000) + .option('--legacy', 'Create separate legacy build') .option('--bundler', 'Specify a bundler (rollup or webpack, blank for auto)') .action(async (dest = 'export', opts: { build: boolean, + legacy: boolean, bundler?: string, 'build-dir': string, basepath?: string, diff --git a/src/cli/build.ts b/src/cli/build.ts index 6b291b6..d13c00e 100644 --- a/src/cli/build.ts +++ b/src/cli/build.ts @@ -4,15 +4,20 @@ import { locations } from '../config'; import validate_bundler from './utils/validate_bundler'; import { repeat } from '../utils'; -export function build(opts: { bundler?: string }) { +export function build(opts: { bundler?: string, legacy?: boolean }) { const bundler = validate_bundler(opts.bundler); + if (opts.legacy && bundler === 'webpack') { + throw new Error(`Legacy builds are not supported for projects using webpack`); + } + return new Promise((fulfil, reject) => { try { const emitter = _build({ dest: locations.dest(), app: locations.app(), routes: locations.routes(), + legacy: opts.legacy, bundler, webpack: 'webpack', rollup: 'rollup' diff --git a/src/middleware.ts b/src/middleware.ts index 7a95873..900bbf1 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -306,7 +306,8 @@ function get_page_handler( const build_info: { bundler: 'rollup' | 'webpack', shimport: string | null, - assets: Record + assets: Record, + legacy_assets?: Record } = get_build_info(); res.setHeader('Content-Type', 'text/html'); @@ -472,14 +473,7 @@ function get_page_handler( store }); - const file = [].concat(build_info.assets.main).filter(file => file && /\.js$/.test(file))[0]; - const main = `${req.baseUrl}/client/${file}`; - - const script = build_info.bundler === 'rollup' - ? `` - : ``; - - let inline_script = `__SAPPER__={${[ + let script = `__SAPPER__={${[ error && `error:1`, `baseUrl:"${req.baseUrl}"`, serialized.preloaded && `preloaded:${serialized.preloaded}`, @@ -488,12 +482,26 @@ function get_page_handler( const has_service_worker = fs.existsSync(path.join(locations.dest(), 'service-worker.js')); if (has_service_worker) { - inline_script += `if ('serviceWorker' in navigator) navigator.serviceWorker.register('${req.baseUrl}/service-worker.js');`; + script += `if('serviceWorker' in navigator)navigator.serviceWorker.register('${req.baseUrl}/service-worker.js');`; + } + + const file = [].concat(build_info.assets.main).filter(file => file && /\.js$/.test(file))[0]; + const main = `${req.baseUrl}/client/${file}`; + + if (build_info.bundler === 'rollup') { + if (build_info.legacy_assets) { + const legacy_main = `${req.baseUrl}/client/legacy/${build_info.legacy_assets.main}`; + script += `(function(){try{eval("async function x(){}");var main="${main}"}catch(e){main="${legacy_main}"};try{new Function("import('"+main+"')")();}catch(e){var s=document.createElement("script");s.src="${req.baseUrl}/client/shimport@${build_info.shimport}.js";s.setAttribute("data-main",main);document.head.appendChild(s);}}());`; + } else { + script += `try{new Function("import('${main}')")();}catch(e){var s=document.createElement("script");s.src="${req.baseUrl}/client/shimport@${build_info.shimport}.js";s.setAttribute("data-main","${main}");document.head.appendChild(s);}`; + } + } else { + script += `${script}`) + .replace('%sapper.scripts%', () => ``) .replace('%sapper.html%', () => html) .replace('%sapper.head%', () => `${head}`) .replace('%sapper.styles%', () => (css && css.code ? `` : '')); diff --git a/src/rollup.ts b/src/rollup.ts index c23014a..399c1a7 100644 --- a/src/rollup.ts +++ b/src/rollup.ts @@ -9,8 +9,11 @@ export default { }, output: () => { + let dir = `${locations.dest()}/client`; + if (process.env.SAPPER_LEGACY_BUILD) dir += `/legacy`; + return { - dir: `${locations.dest()}/client`, + dir, entryFileNames: '[name].[hash].js', chunkFileNames: '[name].[hash].js', format: 'esm'