1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00

Sourcemap and Breakpoint Fixes (#3121)

* Propagate source maps through combine assets step

* Use constant development build id
This commit is contained in:
Kevin Decker 2017-10-19 15:11:37 -05:00 committed by Tim Neutkens
parent f1f83507db
commit 964f229f98
5 changed files with 90 additions and 81 deletions

View file

@ -1,3 +1,5 @@
import { ConcatSource } from 'webpack-sources'
// This plugin combines a set of assets into a single asset // This plugin combines a set of assets into a single asset
// This should be only used with text assets, // This should be only used with text assets,
// otherwise the result is unpredictable. // otherwise the result is unpredictable.
@ -8,23 +10,23 @@ export default class CombineAssetsPlugin {
} }
apply (compiler) { apply (compiler) {
compiler.plugin('after-compile', (compilation, callback) => { compiler.plugin('compilation', (compilation) => {
let newSource = '' compilation.plugin('optimize-chunk-assets', (chunks, callback) => {
this.input.forEach((name) => { const concat = new ConcatSource()
const asset = compilation.assets[name]
if (!asset) return
newSource += `${asset.source()}\n` this.input.forEach((name) => {
const asset = compilation.assets[name]
if (!asset) return
// We keep existing assets since that helps when analyzing the bundle concat.add(asset)
// We keep existing assets since that helps when analyzing the bundle
})
compilation.assets[this.output] = concat
callback()
}) })
compilation.assets[this.output] = {
source: () => newSource,
size: () => newSource.length
}
callback()
}) })
} }
} }

View file

@ -1,39 +1,37 @@
export default class PagesPlugin { import { ConcatSource } from 'webpack-sources'
export default class DynamicChunksPlugin {
apply (compiler) { apply (compiler) {
const isImportChunk = /^chunks[/\\].*\.js$/ const isImportChunk = /^chunks[/\\].*\.js$/
const matchChunkName = /^chunks[/\\](.*)$/ const matchChunkName = /^chunks[/\\](.*)$/
compiler.plugin('after-compile', (compilation, callback) => { compiler.plugin('compilation', (compilation) => {
const chunks = Object compilation.plugin('optimize-chunk-assets', (chunks, callback) => {
.keys(compilation.namedChunks) chunks = chunks.filter(chunk => isImportChunk.test(chunk.name))
.map(key => compilation.namedChunks[key])
.filter(chunk => isImportChunk.test(chunk.name))
chunks.forEach((chunk) => { chunks.forEach((chunk) => {
const asset = compilation.assets[chunk.name] const asset = compilation.assets[chunk.name]
if (!asset) return if (!asset) return
const chunkName = matchChunkName.exec(chunk.name)[1] const chunkName = matchChunkName.exec(chunk.name)[1]
const concat = new ConcatSource()
const content = asset.source() concat.add(`__NEXT_REGISTER_CHUNK('${chunkName}', function() {
const newContent = ` `)
window.__NEXT_REGISTER_CHUNK('${chunkName}', function() { concat.add(asset)
${content} concat.add(`
}) })
` `)
// Replace the exisiting chunk with the new content
compilation.assets[chunk.name] = {
source: () => newContent,
size: () => newContent.length
}
// This is to support, webpack dynamic import support with HMR // Replace the exisiting chunk with the new content
compilation.assets[`chunks/${chunk.id}`] = { compilation.assets[chunk.name] = concat
source: () => newContent,
size: () => newContent.length // This is to support, webpack dynamic import support with HMR
} compilation.assets[`chunks/${chunk.name}`] = concat
})
callback()
}) })
callback()
}) })
} }
} }

View file

@ -1,3 +1,4 @@
import { ConcatSource } from 'webpack-sources'
import { import {
IS_BUNDLED_PAGE, IS_BUNDLED_PAGE,
MATCH_ROUTE_NAME MATCH_ROUTE_NAME
@ -5,43 +6,48 @@ import {
export default class PagesPlugin { export default class PagesPlugin {
apply (compiler) { apply (compiler) {
compiler.plugin('after-compile', (compilation, callback) => { compiler.plugin('compilation', (compilation) => {
const pages = Object compilation.plugin('optimize-chunk-assets', (chunks, callback) => {
.keys(compilation.namedChunks) const pages = chunks.filter(chunk => IS_BUNDLED_PAGE.test(chunk.name))
.map(key => compilation.namedChunks[key])
.filter(chunk => IS_BUNDLED_PAGE.test(chunk.name))
pages.forEach((chunk) => { pages.forEach((chunk) => {
const page = compilation.assets[chunk.name] const pageName = MATCH_ROUTE_NAME.exec(chunk.name)[1]
const pageName = MATCH_ROUTE_NAME.exec(chunk.name)[1] let routeName = pageName
let routeName = pageName
// We need to convert \ into / when we are in windows // We need to convert \ into / when we are in windows
// to get the proper route name // to get the proper route name
// Here we need to do windows check because it's possible // Here we need to do windows check because it's possible
// to have "\" in the filename in unix. // to have "\" in the filename in unix.
// Anyway if someone did that, he'll be having issues here. // Anyway if someone did that, he'll be having issues here.
// But that's something we cannot avoid. // But that's something we cannot avoid.
if (/^win/.test(process.platform)) { if (/^win/.test(process.platform)) {
routeName = routeName.replace(/\\/g, '/') routeName = routeName.replace(/\\/g, '/')
} }
routeName = `/${routeName.replace(/(^|\/)index$/, '')}` routeName = `/${routeName.replace(/(^|\/)index$/, '')}`
const content = page.source() // Replace the exisiting chunk with the new content
const newContent = ` const asset = compilation.assets[chunk.name]
window.__NEXT_REGISTER_PAGE('${routeName}', function() { if (!asset) return
var comp = ${content}
return { page: comp.default } const concat = new ConcatSource()
})
` concat.add(`
// Replace the exisiting chunk with the new content __NEXT_REGISTER_PAGE('${routeName}', function() {
compilation.assets[chunk.name] = { var comp =
source: () => newContent, `)
size: () => newContent.length concat.add(asset)
} concat.add(`
return { page: comp.default }
})
`)
// Replace the exisiting chunk with the new content
compilation.assets[chunk.name] = concat
})
callback()
}) })
callback()
}) })
} }
} }

View file

@ -408,7 +408,11 @@ export default class Server {
} }
handleBuildId (buildId, res) { handleBuildId (buildId, res) {
if (this.dev) return true if (this.dev) {
res.setHeader('Cache-Control', 'no-store, must-revalidate')
return true
}
if (buildId !== this.renderOpts.buildId) { if (buildId !== this.renderOpts.buildId) {
return false return false
} }
@ -428,13 +432,17 @@ export default class Server {
} }
handleBuildHash (filename, hash, res) { handleBuildHash (filename, hash, res) {
if (this.dev) return if (this.dev) {
res.setHeader('Cache-Control', 'no-store, must-revalidate')
return true
}
if (hash !== this.buildStats[filename].hash) { if (hash !== this.buildStats[filename].hash) {
throw new Error(`Invalid Build File Hash(${hash}) for chunk: ${filename}`) throw new Error(`Invalid Build File Hash(${hash}) for chunk: ${filename}`)
} }
res.setHeader('Cache-Control', 'max-age=365000000, immutable') res.setHeader('Cache-Control', 'max-age=365000000, immutable')
return true
} }
send404 (res) { send404 (res) {

View file

@ -93,11 +93,6 @@ async function doRender (req, res, pathname, query, {
} }
const docProps = await loadGetInitialProps(Document, { ...ctx, renderPage }) const docProps = await loadGetInitialProps(Document, { ...ctx, renderPage })
// While developing, we should not cache any assets.
// So, we use a different buildId for each page load.
// With that we can ensure, we have unique URL for assets per every page load.
// So, it'll prevent issues like this: https://git.io/vHLtb
const devBuildId = Date.now()
if (res.finished) return if (res.finished) return
@ -107,7 +102,7 @@ async function doRender (req, res, pathname, query, {
props, props,
pathname, pathname,
query, query,
buildId: dev ? devBuildId : buildId, buildId,
buildStats, buildStats,
assetPrefix, assetPrefix,
nextExport, nextExport,