There's an edge case @timothyis is running into, this will show exactly what files are missing.
I currently can't reproduce, so this is a first step at providing better error messages
The current canary version shows the following warning in development mode:
```log
Warning: Each child in an array or iterator should have a unique "key" prop. See https://fb.me/react-warning-keys for more information.
in script
in NextScript
in body
in html
in Document
```
This PR adds proper keys to the devFiles on the server.
Related https://github.com/zeit/next.js/pull/4954
Depends on https://github.com/zeit/next-plugins/pull/228
Failing tests are expected as `@zeit/next-css` has to be updated/released first.
This implements rendering of `.css` chunks. Effectively removing the custom document requirement when adding next-css/sass/less/stylus.
* Compile pages to .next/static/<buildid>/pages/<page>
* Fix test
* Export class instead of using exports
* Use constant for static directory
* Add comment about what the middleware does
* Add support for custom App and Component enhancers
* Add ctx.renderPage test
* Add tests for single enhancer function
* Cleanup renderPage options check
* Cleanup
* Add comment about backwards compatibility for renderPage
* Add more test cases
This PR fixes#4615
From the issue :
> One thing we might consider is merging and showing a warning for keys not defined in exportPathMap
The behaviour after this PR is the following :
```js
// next.config.js
module.exports = {
exportPathMap: () => ({
'/': { page: '/', query: { a: 'blue' } }
})
}
```
| url called | `ctx.query` | warning ? |
|-|-|-|
| `/` | `{ a: 'blue' }` | |
| `/?a=red` | `{ a: 'blue' }` | |
| `/?b=green` | `{ a: 'blue', b: 'green' }` | `... parameter 'b' missing in exportPathMap` |
Is that the expected behaviour ? If not, I'll update the PR to shape the expected behavior.
I can't use a functional component with `_document.js`.
[is-react](https://www.npmjs.com/package/is-react) can be used for another potential implementation of the warning logic, but maybe relying on `React.createElement()` internal checks is enough.
A follow-up to #4604: the dot in the regexp was not escaped as intended. By default `*` matches greedily, so the results are the same, but the new regexp should be more clear. Sorry for the mistake.
The prepares for next-server.
I also took this as an opportunity to get all build directory paths from a single location, as they were previously scattered across webpack/babel plugins and loaders.
Fixes#4603.
Tests explain it the best:
```js
describe('development mode (no chunkhash)', () => {
it('should strip the extension from the filename', () => {
const filename = 'foo_bar_0123456789abcdef.js'
expect(getChunkNameFromFilename(filename, true)).toBe('foo_bar_0123456789abcdef')
})
it('should only strip the extension even if there\'s a hyphen in the name', () => {
const filename = 'foo-bar-0123456789abcdef.js'
expect(getChunkNameFromFilename(filename, true)).toBe('foo-bar-0123456789abcdef')
})
})
describe('production mode (with chunkhash)', () => {
it('should strip the hash from the filename', () => {
const filename = 'foo_bar_0123456789abcdef-0123456789abcdef.js'
expect(getChunkNameFromFilename(filename, false)).toBe('foo_bar_0123456789abcdef')
})
it('should only strip the part after the last hyphen in the filename', () => {
const filename = 'foo-bar-0123456789abcdef-0123456789abcdef.js'
expect(getChunkNameFromFilename(filename, false)).toBe('foo-bar-0123456789abcdef')
})
})
```
This fixes a missed bug introduced in #4510.
Because the regexp was `/-[^-]*/` and not `/-[^-]*$/`, a wrong part of the filename was being removed:
```
bad:
'foo-bar-0123456789abcdef-0123456789abcdef.js' -> 'foo-0123456789abcdef-0123456789abcdef.js'
good:
'foo-bar-0123456789abcdef-0123456789abcdef.js' -> 'foo-bar-0123456789abcdef'
```
By a stroke of luck this didn't affect the existing dynamically generated chunks. To prevent regression I've added unit tests for the function that generates the name.
Btw. in the original issue (#4433) I used the right regexp, I just used the wrong regexp in #4510.
cc @timneutkens
Fixes one of the problems described in #4433.
The old regexp was removing everything after a hyphen, so with a chunk name like so:
```
chunks/path-to-a-file-[hash].js
```
the saved chunk name was
```
chunks/path
```
This caused problems, because webpack by default changes `/` to `-` in chunk names generated e.g. by ``import(`foo/${bar}`)``.
After this change the chunk name will be
```
chunks/path-to-a-file
```
Since `_app.js` is used on every page it makes sense to move it's dependencies to the `commons.js` so that if you require a dependency in `_app.js` and in one of your pages it is not included twice in your bundles.
This PR modifies the `CommonsChunkPlugin` to move every module that is used in `_app.js` and at least in one other bundle.
Previously we called this directory holding the pages/chunks for server rendering `.next/dist` instead of `.next/server` which is confusing both when looking at it and in the codebase, since there's also `distDir` as a configuration option.
Also made this a constant in `next/constants` so functionality using this can be easily found.
This fixes the generated page chunk created by the webpack `pages-plugin` which adds a new line in the beginning of the template, when using `output.libraryTarget` set to be [`umd`](https://webpack.js.org/configuration/output/#module-definition-systems) it returns the module.
Consider the following example, which is the output with the previous implementation:
```js
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["MyLibrary"] = factory();
else
root["MyLibrary"] = factory();
})(typeof self !== 'undefined' ? self : this, function() {
return
__NEXT_REGISTER_PAGE(...)
});
```
`__NEXT_REGISTER_PAGE()` won't be executed since a `return` statement followed by a new line is the same as having a semicolon inserted right after the `return`. By removing the new line in the beginning of the source concatenation (which I suppose was added for stylistic reasons) this works as expected.
* Don’t use chunkhash in development
* Add test for dynamic imports styling
* Remove pre-load of dynamic page
* Make sure the browser gets closed only once