Skip to content

Commit

Permalink
Move build directory outside of server folder (vercel#4565)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
timneutkens authored and lependu committed Jun 19, 2018
1 parent f6b3755 commit a30ef19
Show file tree
Hide file tree
Showing 30 changed files with 245 additions and 100 deletions.
2 changes: 1 addition & 1 deletion babel.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
module.exports = require('./dist/server/build/babel/preset')
module.exports = require('./dist/build/babel/preset')
2 changes: 1 addition & 1 deletion bin/next-build
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { resolve, join } from 'path'
import { existsSync } from 'fs'
import parseArgs from 'minimist'
import build from '../server/build'
import build from '../build'
import { printAndExit } from '../lib/utils'

const argv = parseArgs(process.argv.slice(2), {
Expand Down
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions server/build/index.js → build/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { join } from 'path'
import promisify from '../lib/promisify'
import fs from 'fs'
import webpack from 'webpack'
import loadConfig from '../config'
import { PHASE_PRODUCTION_BUILD, BUILD_ID_FILE } from '../../lib/constants'
import loadConfig from '../server/config'
import { PHASE_PRODUCTION_BUILD, BUILD_ID_FILE } from '../lib/constants'
import getBaseWebpackConfig from './webpack'

const access = promisify(fs.access)
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { resolve, relative } from 'path'
// @flow
import { relative } from 'path'
import loaderUtils from 'loader-utils'

module.exports = function (content, sourceMap) {
type Options = {|
extensions: RegExp,
include: Array<string>
|}

module.exports = function (content: string, sourceMap: any) {
this.cacheable()

const options = loaderUtils.getOptions(this)
const route = getRoute(this, options)
const options: Options = loaderUtils.getOptions(this)
const route = getRoute(this.resourcePath, options)

// Webpack has a built in system to prevent default from colliding, giving it a random letter per export.
// We can safely check if Component is undefined since all other pages imported into the entrypoint don't have __webpack_exports__.default
Expand All @@ -30,18 +36,21 @@ module.exports = function (content, sourceMap) {
`, sourceMap)
}

const nextPagesDir = resolve(__dirname, '..', '..', '..', 'pages')

function getRoute (loaderContext, options) {
const pagesDir = resolve(loaderContext.options.context, 'pages')
const { resourcePath } = loaderContext
const dir = [pagesDir, nextPagesDir]
.find((d) => resourcePath.indexOf(d) === 0)

function getRoute (resourcePath: string, options: Options) {
if (!options.extensions) {
throw new Error('extensions is not provided to hot-self-accept-loader. Please upgrade all next-plugins to the latest version.')
}

if (!options.include) {
throw new Error('include option is not provided to hot-self-accept-loader. Please upgrade all next-plugins to the latest version.')
}

const dir = options.include.find((d) => resourcePath.indexOf(d) === 0)

if (!dir) {
throw new Error(`'hot-self-accept-loader' was called on a file that isn't a page.`)
}

const path = relative(dir, resourcePath).replace(options.extensions, '.js')
return '/' + path.replace(/((^|\/)index)?\.js$/, '')
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow
import { RawSource } from 'webpack-sources'
import {BUILD_MANIFEST} from '../../../lib/constants'
import {BUILD_MANIFEST} from '../../lib/constants'

// This plugin creates a build-manifest.json for all assets that are being output
// It has a mapping of "entry" filename to real filename. Because the real filename can be hashed in production
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// @flow
import { RawSource } from 'webpack-sources'
import { MATCH_ROUTE_NAME } from '../../utils'
import {PAGES_MANIFEST} from '../../../lib/constants'
import {PAGES_MANIFEST, ROUTE_NAME_REGEX} from '../../lib/constants'

// This plugin creates a pages-manifest.json from page entrypoints.
// This is used for mapping paths like `/` to `.next/dist/bundles/pages/index.js` when doing SSR
Expand All @@ -13,7 +12,7 @@ export default class PagesManifestPlugin {
const pages = {}

for (const entry of entries) {
const result = MATCH_ROUTE_NAME.exec(entry.name)
const result = ROUTE_NAME_REGEX.exec(entry.name)
if (!result) {
continue
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { ConcatSource } from 'webpack-sources'
import {
IS_BUNDLED_PAGE,
MATCH_ROUTE_NAME
} from '../../utils'
IS_BUNDLED_PAGE_REGEX,
ROUTE_NAME_REGEX
} from '../../lib/constants'

class PageChunkTemplatePlugin {
apply (chunkTemplate) {
chunkTemplate.plugin('render', function (modules, chunk) {
if (!IS_BUNDLED_PAGE.test(chunk.name)) {
if (!IS_BUNDLED_PAGE_REGEX.test(chunk.name)) {
return modules
}

let routeName = MATCH_ROUTE_NAME.exec(chunk.name)[1]
let routeName = ROUTE_NAME_REGEX.exec(chunk.name)[1]

// We need to convert \ into / when we are in windows
// to get the proper route name
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { join } from 'path'
import promisify from '../../lib/promisify'
import fs from 'fs'
import { IS_BUNDLED_PAGE } from '../../utils'
import { IS_BUNDLED_PAGE_REGEX } from '../../lib/constants'

const unlink = promisify(fs.unlink)

Expand All @@ -13,7 +13,7 @@ export default class UnlinkFilePlugin {
apply (compiler) {
compiler.plugin('after-emit', (compilation, callback) => {
const removed = Object.keys(this.prevAssets)
.filter((a) => IS_BUNDLED_PAGE.test(a) && !compilation.assets[a])
.filter((a) => IS_BUNDLED_PAGE_REGEX.test(a) && !compilation.assets[a])

this.prevAssets = compilation.assets

Expand Down
41 changes: 19 additions & 22 deletions server/build/webpack.js → build/webpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ import DynamicChunksPlugin from './plugins/dynamic-chunks-plugin'
import UnlinkFilePlugin from './plugins/unlink-file-plugin'
import PagesManifestPlugin from './plugins/pages-manifest-plugin'
import BuildManifestPlugin from './plugins/build-manifest-plugin'
import {SERVER_DIRECTORY} from '../../lib/constants'

const nextDir = path.join(__dirname, '..', '..', '..')
const nextNodeModulesDir = path.join(nextDir, 'node_modules')
const nextPagesDir = path.join(nextDir, 'pages')
import {SERVER_DIRECTORY, NEXT_PROJECT_ROOT, NEXT_PROJECT_ROOT_NODE_MODULES, NEXT_PROJECT_ROOT_DIST, DEFAULT_PAGES_DIR} from '../lib/constants'

function externalsConfig (dir, isServer) {
const externals = []
Expand Down Expand Up @@ -57,6 +53,15 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer
babel: {
loader: 'next-babel-loader',
options: {dev, isServer}
},
hotSelfAccept: {
loader: 'hot-self-accept-loader',
options: {
include: [
path.join(dir, 'pages')
],
extensions: /\.(js|jsx)$/
}
}
}

Expand All @@ -65,13 +70,13 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer
.split(process.platform === 'win32' ? ';' : ':')
.filter((p) => !!p)

const pagesEntries = await getPages(dir, {dev, isServer, pageExtensions: config.pageExtensions.join('|')})
const pagesEntries = await getPages(dir, {nextPagesDir: DEFAULT_PAGES_DIR, dev, isServer, pageExtensions: config.pageExtensions.join('|')})
const totalPages = Object.keys(pagesEntries).length
const clientEntries = !isServer ? {
'main.js': [
dev && !isServer && path.join(__dirname, '..', '..', 'client', 'webpack-hot-middleware-client'),
dev && !isServer && path.join(__dirname, '..', '..', 'client', 'on-demand-entries-client'),
require.resolve(`../../client/next${dev ? '-dev' : ''}`)
dev && !isServer && path.join(NEXT_PROJECT_ROOT_DIST, 'client', 'webpack-hot-middleware-client'),
dev && !isServer && path.join(NEXT_PROJECT_ROOT_DIST, 'client', 'on-demand-entries-client'),
path.join(NEXT_PROJECT_ROOT_DIST, 'client', (dev ? `next-dev` : 'next'))
].filter(Boolean)
} : {}

Expand Down Expand Up @@ -102,17 +107,17 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer
resolve: {
extensions: ['.js', '.jsx', '.json'],
modules: [
nextNodeModulesDir,
NEXT_PROJECT_ROOT_NODE_MODULES,
'node_modules',
...nodePathList // Support for NODE_PATH environment variable
],
alias: {
next: nextDir
next: NEXT_PROJECT_ROOT
}
},
resolveLoader: {
modules: [
nextNodeModulesDir,
NEXT_PROJECT_ROOT_NODE_MODULES,
'node_modules',
path.join(__dirname, 'loaders'),
...nodePathList // Support for NODE_PATH environment variable
Expand All @@ -122,14 +127,8 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer
rules: [
dev && !isServer && {
test: /\.(js|jsx)$/,
loader: 'hot-self-accept-loader',
include: [
path.join(dir, 'pages'),
nextPagesDir
],
options: {
extensions: /\.(js|jsx)$/
}
include: defaultLoaders.hotSelfAccept.options.include,
use: defaultLoaders.hotSelfAccept
},
{
test: /\.(js|jsx)$/,
Expand Down Expand Up @@ -206,15 +205,13 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer
return true
}

// commons
// If there are one or two pages, only move modules to common if they are
// used in all of the pages. Otherwise, move modules used in at-least
// 1/2 of the total pages into commons.
if (totalPages <= 2) {
return count >= totalPages
}
return count >= totalPages * 0.5
// commons end
}
}),
// We use a manifest file in development to speed up HMR
Expand Down
8 changes: 3 additions & 5 deletions server/build/webpack/utils.js → build/webpack/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ import globModule from 'glob'

const glob = promisify(globModule)

const nextPagesDir = path.join(__dirname, '..', '..', '..', 'pages')

export async function getPages (dir, {dev, isServer, pageExtensions}) {
export async function getPages (dir, {nextPagesDir, dev, isServer, pageExtensions}) {
const pageFiles = await getPagePaths(dir, {dev, isServer, pageExtensions})

return getPageEntries(pageFiles, {isServer, pageExtensions})
return getPageEntries(pageFiles, {nextPagesDir, isServer, pageExtensions})
}

export async function getPagePaths (dir, {dev, isServer, pageExtensions}) {
Expand Down Expand Up @@ -50,7 +48,7 @@ export function createEntry (filePath, {name, pageExtensions} = {}) {
}

// Convert page paths into entries
export function getPageEntries (pagePaths, {isServer = false, pageExtensions} = {}) {
export function getPageEntries (pagePaths, {nextPagesDir, isServer = false, pageExtensions} = {}) {
const entries = {}

for (const filePath of pagePaths) {
Expand Down
102 changes: 102 additions & 0 deletions flow-typed/npm/loader-utils_vx.x.x.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// flow-typed signature: fbec9bc08efb50bade7bd6c2bab84e41
// flow-typed version: <<STUB>>/loader-utils_v1.1.0/flow_v0.73.0

/**
* This is an autogenerated libdef stub for:
*
* 'loader-utils'
*
* Fill this stub out by replacing all the `any` types.
*
* Once filled out, we encourage you to share your work with the
* community by sending a pull request to:
* https://github.com/flowtype/flow-typed
*/

declare module 'loader-utils' {
declare module.exports: any;
}

/**
* We include stubs for each file inside this npm package in case you need to
* require those files directly. Feel free to delete any files that aren't
* needed.
*/
declare module 'loader-utils/lib/getCurrentRequest' {
declare module.exports: any;
}

declare module 'loader-utils/lib/getHashDigest' {
declare module.exports: any;
}

declare module 'loader-utils/lib/getOptions' {
declare module.exports: any;
}

declare module 'loader-utils/lib/getRemainingRequest' {
declare module.exports: any;
}

declare module 'loader-utils/lib/index' {
declare module.exports: any;
}

declare module 'loader-utils/lib/interpolateName' {
declare module.exports: any;
}

declare module 'loader-utils/lib/isUrlRequest' {
declare module.exports: any;
}

declare module 'loader-utils/lib/parseQuery' {
declare module.exports: any;
}

declare module 'loader-utils/lib/parseString' {
declare module.exports: any;
}

declare module 'loader-utils/lib/stringifyRequest' {
declare module.exports: any;
}

declare module 'loader-utils/lib/urlToRequest' {
declare module.exports: any;
}

// Filename aliases
declare module 'loader-utils/lib/getCurrentRequest.js' {
declare module.exports: $Exports<'loader-utils/lib/getCurrentRequest'>;
}
declare module 'loader-utils/lib/getHashDigest.js' {
declare module.exports: $Exports<'loader-utils/lib/getHashDigest'>;
}
declare module 'loader-utils/lib/getOptions.js' {
declare module.exports: $Exports<'loader-utils/lib/getOptions'>;
}
declare module 'loader-utils/lib/getRemainingRequest.js' {
declare module.exports: $Exports<'loader-utils/lib/getRemainingRequest'>;
}
declare module 'loader-utils/lib/index.js' {
declare module.exports: $Exports<'loader-utils/lib/index'>;
}
declare module 'loader-utils/lib/interpolateName.js' {
declare module.exports: $Exports<'loader-utils/lib/interpolateName'>;
}
declare module 'loader-utils/lib/isUrlRequest.js' {
declare module.exports: $Exports<'loader-utils/lib/isUrlRequest'>;
}
declare module 'loader-utils/lib/parseQuery.js' {
declare module.exports: $Exports<'loader-utils/lib/parseQuery'>;
}
declare module 'loader-utils/lib/parseString.js' {
declare module.exports: $Exports<'loader-utils/lib/parseString'>;
}
declare module 'loader-utils/lib/stringifyRequest.js' {
declare module.exports: $Exports<'loader-utils/lib/stringifyRequest'>;
}
declare module 'loader-utils/lib/urlToRequest.js' {
declare module.exports: $Exports<'loader-utils/lib/urlToRequest'>;
}
7 changes: 7 additions & 0 deletions lib/constants.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {join} from 'path'
export const PHASE_EXPORT = 'phase-export'
export const PHASE_PRODUCTION_BUILD = 'phase-production-build'
export const PHASE_PRODUCTION_SERVER = 'phase-production-server'
Expand All @@ -12,3 +13,9 @@ export const BLOCKED_PAGES = [
'/_app',
'/_error'
]
export const IS_BUNDLED_PAGE_REGEX = /^bundles[/\\]pages.*\.js$/
export const ROUTE_NAME_REGEX = /^bundles[/\\]pages[/\\](.*)\.js$/
export const NEXT_PROJECT_ROOT = join(__dirname, '..', '..')
export const NEXT_PROJECT_ROOT_DIST = join(NEXT_PROJECT_ROOT, 'dist')
export const NEXT_PROJECT_ROOT_NODE_MODULES = join(NEXT_PROJECT_ROOT, 'node_modules')
export const DEFAULT_PAGES_DIR = join(NEXT_PROJECT_ROOT_DIST, 'pages')
File renamed without changes.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"test": "cross-env npm run testall || npm run testall",
"coveralls": "nyc --instrument=false --source-map=false report --temp-directory=./coverage --reporter=text-lcov | coveralls",
"flow": "flow check",
"lint": "standard 'bin/*' 'client/**/*.js' 'examples/**/*.js' 'lib/**/*.js' 'pages/**/*.js' 'server/**/*.js' 'test/**/*.js'",
"lint": "standard 'bin/*' 'client/**/*.js' 'examples/**/*.js' 'lib/**/*.js' 'pages/**/*.js' 'server/**/*.js' 'build/**/*.js' 'test/**/*.js'",
"prepublish": "npm run release",
"precommit": "lint-staged"
},
Expand Down
Loading

0 comments on commit a30ef19

Please sign in to comment.