rsnext/server/build/webpack.js

208 lines
5.6 KiB
JavaScript
Raw Normal View History

2016-10-15 18:17:27 +02:00
import { resolve, join } from 'path'
import { createHash } from 'crypto'
2016-10-14 17:05:08 +02:00
import webpack from 'webpack'
import glob from 'glob-promise'
2016-10-15 21:49:42 +02:00
import WriteFilePlugin from 'write-file-webpack-plugin'
import FriendlyErrorsWebpackPlugin from 'friendly-errors-webpack-plugin'
2016-10-23 18:42:13 +02:00
import UnlinkFilePlugin from './plugins/unlink-file-plugin'
import WatchPagesPlugin from './plugins/watch-pages-plugin'
import WatchRemoveEventPlugin from './plugins/watch-remove-event-plugin'
import DynamicEntryPlugin from './plugins/dynamic-entry-plugin'
import DetachPlugin from './plugins/detach-plugin'
import getConfig from '../config'
2016-10-14 17:05:08 +02:00
2016-12-21 15:39:08 +01:00
export default async function createCompiler (dir, { dev = false, quiet = false } = {}) {
2016-10-15 18:17:27 +02:00
dir = resolve(dir)
const config = getConfig(dir)
2016-10-15 18:17:27 +02:00
2016-12-16 19:42:40 +01:00
const pages = await glob('pages/**/*.js', {
cwd: dir,
ignore: 'pages/_document.js'
})
2016-10-14 17:05:08 +02:00
const entry = {
'main.js': dev ? require.resolve('../../client/next-dev') : require.resolve('../../client/next')
}
const defaultEntries = dev
? [join(__dirname, '..', '..', 'client/webpack-hot-middleware-client')] : []
2016-10-14 17:05:08 +02:00
for (const p of pages) {
entry[join('bundles', p)] = defaultEntries.concat([`./${p}?entry`])
2016-10-14 17:05:08 +02:00
}
2016-10-19 14:58:08 +02:00
const nextPagesDir = join(__dirname, '..', '..', 'pages')
2016-10-19 14:41:45 +02:00
2016-10-17 05:55:09 +02:00
const errorEntry = join('bundles', 'pages', '_error.js')
2016-10-19 14:58:08 +02:00
const defaultErrorPath = join(nextPagesDir, '_error.js')
if (!entry[errorEntry]) {
entry[errorEntry] = defaultEntries.concat([defaultErrorPath + '?entry'])
}
2016-10-14 17:05:08 +02:00
2016-10-19 14:41:45 +02:00
const errorDebugEntry = join('bundles', 'pages', '_error-debug.js')
2016-10-19 14:58:08 +02:00
const errorDebugPath = join(nextPagesDir, '_error-debug.js')
2016-12-25 21:03:07 +01:00
entry[errorDebugEntry] = defaultEntries.concat([errorDebugPath + '?entry'])
2016-10-19 14:41:45 +02:00
2016-10-19 14:58:08 +02:00
const nodeModulesDir = join(__dirname, '..', '..', '..', 'node_modules')
2016-10-14 17:05:08 +02:00
2016-10-16 04:49:09 +02:00
const plugins = [
2016-10-18 16:14:00 +02:00
new WriteFilePlugin({
exitOnErrors: false,
2016-10-23 18:42:13 +02:00
log: false,
// required not to cache removed files
useHashIndex: false
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'commons',
filename: 'commons.js',
minChunks: Math.max(2, pages.length)
2016-10-23 18:42:13 +02:00
})
]
if (dev) {
plugins.push(
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new DetachPlugin(),
new DynamicEntryPlugin(),
new UnlinkFilePlugin(),
new WatchRemoveEventPlugin(),
2016-12-21 15:39:08 +01:00
new WatchPagesPlugin(dir)
)
2016-12-21 15:39:08 +01:00
if (!quiet) {
plugins.push(new FriendlyErrorsWebpackPlugin())
}
} else {
plugins.push(
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false },
sourceMap: false
})
)
}
2016-10-15 21:49:42 +02:00
let mainBabelOptions = {
babelrc: false,
cacheDirectory: true,
sourceMaps: dev ? 'both' : false,
presets: [
require.resolve('./babel/preset')
]
}
if (config.babel) {
console.log('> Using "babel" config function defined in next.config.js.')
mainBabelOptions = await config.babel(mainBabelOptions, { dev })
}
const loaders = (dev ? [{
test: /\.js(\?[^?]*)?$/,
loader: 'hot-self-accept-loader',
include: [
join(dir, 'pages'),
nextPagesDir
]
2016-12-05 18:09:38 +01:00
}, {
test: /\.js(\?[^?]*)?$/,
2016-12-05 18:09:38 +01:00
loader: 'react-hot-loader/webpack',
exclude: /node_modules/
}] : [])
.concat([{
test: /\.json$/,
loader: 'json-loader'
}, {
test: /\.(js|json)(\?[^?]*)?$/,
2016-10-15 18:17:27 +02:00
loader: 'emit-file-loader',
2016-10-19 14:41:45 +02:00
include: [dir, nextPagesDir],
2016-10-25 11:11:39 +02:00
exclude (str) {
return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0
},
2016-10-15 18:17:27 +02:00
query: {
2016-10-17 05:55:09 +02:00
name: 'dist/[path][name].[ext]'
2016-10-15 18:17:27 +02:00
}
}, {
loader: 'babel',
include: nextPagesDir,
query: {
2016-12-11 10:09:54 +01:00
babelrc: false,
cacheDirectory: true,
sourceMaps: dev ? 'both' : false,
plugins: [
[
require.resolve('babel-plugin-module-resolver'),
{
alias: {
'ansi-html': require.resolve('ansi-html'),
'styled-jsx/style': require.resolve('styled-jsx/style')
}
}
]
]
}
}, {
test: /\.js(\?[^?]*)?$/,
2016-10-14 17:05:08 +02:00
loader: 'babel',
2016-10-19 14:41:45 +02:00
include: [dir, nextPagesDir],
2016-10-25 11:11:39 +02:00
exclude (str) {
return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0
2016-10-25 11:11:39 +02:00
},
query: mainBabelOptions
2016-10-19 14:41:45 +02:00
}])
const interpolateNames = new Map([
[defaultErrorPath, 'dist/pages/_error.js'],
[errorDebugPath, 'dist/pages/_error-debug.js']
])
2016-10-14 17:05:08 +02:00
let webpackConfig = {
2016-10-14 17:05:08 +02:00
context: dir,
entry,
output: {
2016-10-19 14:58:08 +02:00
path: join(dir, '.next'),
2016-10-14 17:05:08 +02:00
filename: '[name]',
libraryTarget: 'commonjs2',
publicPath: dev ? '/_webpack/' : null,
devtoolModuleFilenameTemplate ({ resourcePath }) {
const hash = createHash('sha1')
hash.update(Date.now() + '')
const id = hash.digest('hex').slice(0, 7)
// append hash id for cache busting
return `webpack:///${resourcePath}?${id}`
}
2016-10-14 17:05:08 +02:00
},
resolve: {
root: [
nodeModulesDir,
2016-10-19 14:58:08 +02:00
join(dir, 'node_modules')
].concat(
(process.env.NODE_PATH || '')
.split(process.platform === 'win32' ? ';' : ':')
)
2016-10-14 17:05:08 +02:00
},
resolveLoader: {
root: [
nodeModulesDir,
2016-10-19 14:58:08 +02:00
join(__dirname, 'loaders')
2016-10-14 17:05:08 +02:00
]
},
2016-10-15 21:49:42 +02:00
plugins,
2016-10-14 17:05:08 +02:00
module: {
loaders
2016-10-16 06:01:17 +02:00
},
devtool: dev ? 'inline-source-map' : false,
2016-10-16 06:01:17 +02:00
customInterpolateName: function (url, name, opts) {
2016-10-19 14:41:45 +02:00
return interpolateNames.get(this.resourcePath) || url
2016-10-14 17:05:08 +02:00
}
}
if (config.webpack) {
console.log('> Using "webpack" config function defined in next.config.js.')
webpackConfig = await config.webpack(webpackConfig, { dev })
}
return webpack(webpackConfig)
2016-10-14 17:05:08 +02:00
}