diff --git a/examples/with-dynamic-import/next.config.js b/examples/with-dynamic-import/next.config.js new file mode 100644 index 00000000..919b7305 --- /dev/null +++ b/examples/with-dynamic-import/next.config.js @@ -0,0 +1,8 @@ +module.exports = { + exportPathMap: function () { + return { + '/': { page: '/' }, + '/about': { page: '/about' } + } + } +} diff --git a/examples/with-dynamic-import/package.json b/examples/with-dynamic-import/package.json index 1c48a0e7..d88d802d 100644 --- a/examples/with-dynamic-import/package.json +++ b/examples/with-dynamic-import/package.json @@ -6,11 +6,11 @@ "scripts": { "dev": "next", "build": "next build", + "export": "next export", "start": "next start" }, "dependencies": { - "async-reactor": "^1.1.1", - "next": "^3.0.1-beta.5", + "next": "^3.0.6", "react": "^15.4.2", "react-dom": "^15.4.2" }, diff --git a/examples/with-dynamic-import/pages/index.js b/examples/with-dynamic-import/pages/index.js index 5df4ae7e..6e4a9a01 100644 --- a/examples/with-dynamic-import/pages/index.js +++ b/examples/with-dynamic-import/pages/index.js @@ -3,7 +3,6 @@ import Router from 'next/router' import Header from '../components/Header' import Counter from '../components/Counter' import dynamic from 'next/dynamic' -import { asyncReactor } from 'async-reactor' const DynamicComponent = dynamic(import('../components/hello1')) const DynamicComponentWithCustomLoading = dynamic( @@ -16,11 +15,6 @@ const DynamicComponentWithNoSSR = dynamic( import('../components/hello3'), { ssr: false } ) -const DynamicComponentWithAsyncReactor = asyncReactor(async () => { - const Hello4 = await import('../components/hello4') - return () -}) - const DynamicComponent5 = dynamic(import('../components/hello5')) const DynamicBundle = dynamic({ @@ -67,7 +61,6 @@ export default class Index extends React.Component { - { diff --git a/server/build/index.js b/server/build/index.js index 90d2fe5a..92682dd6 100644 --- a/server/build/index.js +++ b/server/build/index.js @@ -8,13 +8,14 @@ import replaceCurrentBuild from './replace' import md5File from 'md5-file/promise' export default async function build (dir, conf = null) { + const buildId = uuid.v4() const buildDir = join(tmpdir(), uuid.v4()) - const compiler = await webpack(dir, { buildDir, conf }) + const compiler = await webpack(dir, { buildId, buildDir, conf }) try { await runCompiler(compiler) await writeBuildStats(buildDir) - await writeBuildId(buildDir) + await writeBuildId(buildDir, buildId) } catch (err) { console.error(`> Failed to build on ${buildDir}`) throw err @@ -59,8 +60,7 @@ async function writeBuildStats (dir) { await fs.writeFile(buildStatsPath, JSON.stringify(assetHashMap), 'utf8') } -async function writeBuildId (dir) { +async function writeBuildId (dir, buildId) { const buildIdPath = join(dir, '.next', 'BUILD_ID') - const buildId = uuid.v4() await fs.writeFile(buildIdPath, buildId, 'utf8') } diff --git a/server/build/webpack.js b/server/build/webpack.js index 7fd93d57..eb743758 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -27,7 +27,7 @@ const interpolateNames = new Map(defaultPages.map((p) => { const relativeResolve = rootModuleRelativePath(require) -export default async function createCompiler (dir, { dev = false, quiet = false, buildDir, conf = null } = {}) { +export default async function createCompiler (dir, { buildId, dev = false, quiet = false, buildDir, conf = null } = {}) { dir = resolve(dir) const config = getConfig(dir, conf) const defaultEntries = dev ? [ @@ -296,7 +296,7 @@ export default async function createCompiler (dir, { dev = false, quiet = false, path: buildDir ? join(buildDir, '.next') : join(dir, config.distDir), filename: '[name]', libraryTarget: 'commonjs2', - publicPath: '/_next/webpack/', + publicPath: `/_next/${buildId}/webpack/`, strictModuleExceptionHandling: true, devtoolModuleFilenameTemplate ({ resourcePath }) { const hash = createHash('sha1') diff --git a/server/document.js b/server/document.js index 402c105f..a536f2d7 100644 --- a/server/document.js +++ b/server/document.js @@ -67,12 +67,12 @@ export class Head extends Component { getPreloadDynamicChunks () { const { chunks, __NEXT_DATA__ } = this.context._documentProps - let { assetPrefix } = __NEXT_DATA__ + let { assetPrefix, buildId } = __NEXT_DATA__ return chunks.map((chunk) => ( )) @@ -153,7 +153,7 @@ export class NextScript extends Component { getDynamicChunks () { const { chunks, __NEXT_DATA__ } = this.context._documentProps - let { assetPrefix } = __NEXT_DATA__ + let { assetPrefix, buildId } = __NEXT_DATA__ return (
{chunks.map((chunk) => ( @@ -161,7 +161,7 @@ export class NextScript extends Component { async key={chunk} type='text/javascript' - src={`${assetPrefix}/_next/webpack/chunks/${chunk}`} + src={`${assetPrefix}/_next/${buildId}/webpack/chunks/${chunk}`} /> ))}
diff --git a/server/export.js b/server/export.js index 5f1818fc..fe098740 100644 --- a/server/export.js +++ b/server/export.js @@ -51,10 +51,10 @@ export default async function (dir, options) { if (existsSync(join(nextDir, 'chunks'))) { log(' copying dynamic import chunks') - await mkdirp(join(outDir, '_next', 'webpack')) + await mkdirp(join(outDir, '_next', buildId, 'webpack')) await cp( join(nextDir, 'chunks'), - join(outDir, '_next', 'webpack', 'chunks') + join(outDir, '_next', buildId, 'webpack', 'chunks') ) } diff --git a/server/hot-reloader.js b/server/hot-reloader.js index cd429390..3cebfb28 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -5,6 +5,7 @@ import onDemandEntryHandler from './on-demand-entry-handler' import webpack from './build/webpack' import clean from './build/clean' import getConfig from './config' +import UUID from 'uuid' import { IS_BUNDLED_PAGE } from './utils' @@ -23,6 +24,11 @@ export default class HotReloader { this.prevChunkNames = null this.prevFailedChunkNames = null this.prevChunkHashes = null + // Here buildId could be any value. + // Our router accepts any value in the dev mode. + // But for the webpack-compiler and for the webpack-dev-server + // it should be the same value. + this.buildId = UUID.v4() this.config = getConfig(dir, conf) } @@ -40,7 +46,7 @@ export default class HotReloader { async start () { const [compiler] = await Promise.all([ - webpack(this.dir, { dev: true, quiet: this.quiet }), + webpack(this.dir, { buildId: this.buildId, dev: true, quiet: this.quiet }), clean(this.dir) ]) @@ -66,7 +72,7 @@ export default class HotReloader { this.stats = null const [compiler] = await Promise.all([ - webpack(this.dir, { dev: true, quiet: this.quiet }), + webpack(this.dir, { buildId: this.buildId, dev: true, quiet: this.quiet }), clean(this.dir) ]) @@ -173,7 +179,7 @@ export default class HotReloader { ] let webpackDevMiddlewareConfig = { - publicPath: '/_next/webpack/', + publicPath: `/_next/${this.buildId}/webpack/`, noInfo: true, quiet: true, clientLogLevel: 'warning', diff --git a/server/index.js b/server/index.js index 1900ccfd..6b453135 100644 --- a/server/index.js +++ b/server/index.js @@ -123,14 +123,21 @@ export default class Server { }, // This is to support, webpack dynamic imports in production. - '/_next/webpack/chunks/:name': async (req, res, params) => { - res.setHeader('Cache-Control', 'max-age=365000000, immutable') + '/_next/:buildId/webpack/chunks/:name': async (req, res, params) => { + if (!this.handleBuildId(params.buildId, res)) { + return this.send404(res) + } + const p = join(this.dir, this.dist, 'chunks', params.name) await this.serveStatic(req, res, p) }, // This is to support, webpack dynamic import support with HMR - '/_next/webpack/:id': async (req, res, params) => { + '/_next/:buildId/webpack/:id': async (req, res, params) => { + if (!this.handleBuildId(params.buildId, res)) { + return this.send404(res) + } + const p = join(this.dir, this.dist, 'chunks', params.id) await this.serveStatic(req, res, p) },