diff --git a/src/cli.ts b/src/cli.ts index 8913b9f..508d308 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -21,9 +21,18 @@ prog.command('dev') prog.command('build [dest]') .describe('Create a production-ready version of your app') - .action(async (dest = 'build') => { + .option('-l, --launcher', 'Create a launcher file (defaults to start.js)') + .option('-p, --port', 'Default port, if using --launcher') + .example(`build -l`) + .example(`build custom-dir -l custom-launcher.js -p 4567`) + .action(async (dest = 'build', opts: { launcher: string | true, port: string }) => { console.log(`> Building...`); + if (opts.port && !opts.launcher) { + console.error(`${clorox.bold.red(`You can only use the --port option with --launcher`)}`); + process.exit(1); + } + process.env.NODE_ENV = 'production'; process.env.SAPPER_DEST = dest; @@ -32,7 +41,31 @@ prog.command('build [dest]') try { const { build } = await import('./cli/build'); await build(); - console.error(`\n> Finished in ${elapsed(start)}. Type ${clorox.bold.cyan(dest === 'build' ? 'npx sapper start' : `npx sapper start ${dest}`)} to run the app.`); + + let cmd; + + if (opts.launcher) { + const launcher = opts.launcher === true ? 'start.js' : opts.launcher; + const resolvedLauncher = path.resolve(launcher); + const resolvedDest = path.resolve(dest); + const relative = path.relative(path.dirname(resolvedLauncher), resolvedDest); + + fs.writeFileSync(resolvedLauncher, ` + // generated by sapper build at ${new Date().toISOString()} + process.env.NODE_ENV = process.env.NODE_ENV || 'production'; + process.env.SAPPER_DEST = require('path').resolve(__dirname, '${relative}'); + process.env.PORT = process.env.PORT || ${opts.port || 3000}; + + console.log('Starting server on port ' + process.env.PORT); + require('${relative[0] === '.' ? relative : `./${relative}`}/server.js'); + `.replace(/^\t+/gm, '').trim()); + + cmd = `node ${path.relative(process.cwd(), launcher)}`; + } else { + cmd = dest === 'build' ? 'npx sapper start' : `npx sapper start ${dest}`; + } + + console.error(`\n> Finished in ${elapsed(start)}. Type ${clorox.bold.cyan(cmd)} to run the app.`); } catch (err) { console.error(err ? err.details || err.stack || err.message || err : 'Unknown error'); } diff --git a/test/app/start.js b/test/app/start.js new file mode 100644 index 0000000..42937e3 --- /dev/null +++ b/test/app/start.js @@ -0,0 +1,7 @@ +// generated by sapper build at 2018-05-04T03:03:00.914Z +process.env.NODE_ENV = process.env.NODE_ENV || 'production'; +process.env.SAPPER_DEST = require('path').resolve(__dirname, 'build'); +process.env.PORT = process.env.PORT || 3000; + +console.log('Starting server on port ' + process.env.PORT); +require('./build/server.js'); \ No newline at end of file diff --git a/test/common/test.js b/test/common/test.js index 6135160..3c328c6 100644 --- a/test/common/test.js +++ b/test/common/test.js @@ -1,3 +1,4 @@ +const fs = require('fs'); const path = require('path'); const assert = require('assert'); const Nightmare = require('nightmare'); @@ -38,6 +39,7 @@ describe('sapper', function() { rimraf.sync('export'); rimraf.sync('build'); rimraf.sync('.sapper'); + rimraf.sync('start.js'); this.timeout(process.env.CI ? 30000 : 10000); @@ -148,7 +150,7 @@ function run({ mode, basepath = '' }) { before(() => { const promise = mode === 'production' - ? exec(`node ${cli} build`).then(() => ports.find(3000)) + ? exec(`node ${cli} build -l`).then(() => ports.find(3000)) : ports.find(3000).then(port => { exec(`node ${cli} dev`); return ports.wait(port).then(() => port); @@ -160,6 +162,10 @@ function run({ mode, basepath = '' }) { const dir = mode === 'production' ? 'build' : '.sapper'; + if (mode === 'production') { + assert.ok(fs.existsSync('start.js')); + } + proc = require('child_process').fork(`${dir}/server.js`, { cwd: process.cwd(), env: {