UNPKG

@tdb/web

Version:

Common condiguration for serving a web-site and testing web-based UI components.

397 lines (335 loc) 16.7 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getBaseWebpackConfig; var _stringify = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/json/stringify")); var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator")); var _objectSpread2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/objectSpread")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/toConsumableArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty")); var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator")); var _path = _interopRequireDefault(require("path")); var _webpack = _interopRequireDefault(require("webpack")); var _resolve = _interopRequireDefault(require("resolve")); var _caseSensitivePathsWebpackPlugin = _interopRequireDefault(require("case-sensitive-paths-webpack-plugin")); var _writeFileWebpackPlugin = _interopRequireDefault(require("write-file-webpack-plugin")); var _friendlyErrorsWebpackPlugin = _interopRequireDefault(require("friendly-errors-webpack-plugin")); var _webpackbar = _interopRequireDefault(require("webpackbar")); var _utils = require("./webpack/utils"); var _pagesPlugin = _interopRequireDefault(require("./webpack/plugins/pages-plugin")); var _nextjsSsrImport = _interopRequireDefault(require("./webpack/plugins/nextjs-ssr-import")); var _nextjsSsrModuleCache = _interopRequireDefault(require("./webpack/plugins/nextjs-ssr-module-cache")); var _nextjsRequireCacheHotReloader = _interopRequireDefault(require("./webpack/plugins/nextjs-require-cache-hot-reloader")); var _unlinkFilePlugin = _interopRequireDefault(require("./webpack/plugins/unlink-file-plugin")); var _pagesManifestPlugin = _interopRequireDefault(require("./webpack/plugins/pages-manifest-plugin")); var _buildManifestPlugin = _interopRequireDefault(require("./webpack/plugins/build-manifest-plugin")); var _chunkNamesPlugin = _interopRequireDefault(require("./webpack/plugins/chunk-names-plugin")); var _reactLoadablePlugin = require("./webpack/plugins/react-loadable-plugin"); var _constants = require("../lib/constants"); var _autodllWebpackPlugin = _interopRequireDefault(require("autodll-webpack-plugin")); var _terserWebpackPlugin = _interopRequireDefault(require("terser-webpack-plugin")); // The externals config makes sure that // on the server side when modules are // in node_modules they don't get compiled by webpack function externalsConfig(dir, isServer) { var externals = []; if (!isServer) { return externals; } externals.push(function (context, request, callback) { (0, _resolve.default)(request, { basedir: dir, preserveSymlinks: true }, function (err, res) { if (err) { return callback(); } // Default pages have to be transpiled if (res.match(/node_modules[/\\]next[/\\]dist[/\\]pages/)) { return callback(); } // Webpack itself has to be compiled because it doesn't always use module relative paths if (res.match(/node_modules[/\\]webpack/) || res.match(/node_modules[/\\]css-loader/)) { return callback(); } if (res.match(/node_modules[/\\].*\.js$/)) { return callback(null, "commonjs ".concat(request)); } callback(); }); }); return externals; } function optimizationConfig(_ref) { var dir = _ref.dir, dev = _ref.dev, isServer = _ref.isServer, totalPages = _ref.totalPages; if (isServer) { return { splitChunks: false, minimize: false }; } var config = { runtimeChunk: { name: _constants.CLIENT_STATIC_FILES_RUNTIME_WEBPACK }, splitChunks: { cacheGroups: { default: false, vendors: false } } }; if (dev) { return config; } // Terser is a better uglifier config.minimizer = [new _terserWebpackPlugin.default({ parallel: true, sourceMap: false, cache: true })]; // Only enabled in production // This logic will create a commons bundle // with modules that are used in 50% of all pages config.splitChunks.chunks = 'all'; config.splitChunks.cacheGroups.commons = { name: 'commons', chunks: 'all', minChunks: totalPages > 2 ? totalPages * 0.5 : 2 }; config.splitChunks.cacheGroups.react = { name: 'commons', chunks: 'all', test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/ }; return config; } function getBaseWebpackConfig(_x, _x2) { return _getBaseWebpackConfig.apply(this, arguments); } function _getBaseWebpackConfig() { _getBaseWebpackConfig = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee3(dir, _ref2) { var _ref2$dev, dev, _ref2$isServer, isServer, buildId, config, defaultLoaders, nodePathList, distDir, outputPath, pagesEntries, totalPages, clientEntries, resolveConfig, webpackMode, webpackConfig, originalEntry; return _regenerator.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: _ref2$dev = _ref2.dev, dev = _ref2$dev === void 0 ? false : _ref2$dev, _ref2$isServer = _ref2.isServer, isServer = _ref2$isServer === void 0 ? false : _ref2$isServer, buildId = _ref2.buildId, config = _ref2.config; defaultLoaders = { babel: { loader: 'next-babel-loader', options: { dev: dev, isServer: isServer, cwd: dir } }, hotSelfAccept: { loader: 'hot-self-accept-loader', options: { include: [_path.default.join(dir, 'pages')], // All pages are javascript files. So we apply hot-self-accept-loader here to facilitate hot reloading of pages. // This makes sure plugins just have to implement `pageExtensions` instead of also implementing the loader extensions: new RegExp("\\.+(".concat(config.pageExtensions.join('|'), ")$")) } } // Support for NODE_PATH }; nodePathList = (process.env.NODE_PATH || '').split(process.platform === 'win32' ? ';' : ':').filter(function (p) { return !!p; }); distDir = _path.default.join(dir, config.distDir); outputPath = _path.default.join(distDir, isServer ? _constants.SERVER_DIRECTORY : ''); _context3.next = 7; return (0, _utils.getPages)(dir, { nextPagesDir: _constants.DEFAULT_PAGES_DIR, dev: dev, buildId: buildId, isServer: isServer, pageExtensions: config.pageExtensions.join('|') }); case 7: pagesEntries = _context3.sent; totalPages = (0, _keys.default)(pagesEntries).length; clientEntries = !isServer ? (0, _defineProperty2.default)({ // Backwards compatibility 'main.js': [] }, _constants.CLIENT_STATIC_FILES_RUNTIME_MAIN, [_path.default.join(_constants.NEXT_PROJECT_ROOT_DIST, 'client', dev ? "next-dev" : 'next')].filter(Boolean)) : {}; resolveConfig = { extensions: ['.wasm', '.mjs', '.js', '.jsx', '.json'], modules: [_constants.NEXT_PROJECT_ROOT_NODE_MODULES, 'node_modules'].concat((0, _toConsumableArray2.default)(nodePathList)), alias: { next: _constants.NEXT_PROJECT_ROOT } }; webpackMode = dev ? 'development' : 'production'; webpackConfig = { mode: webpackMode, devtool: dev ? 'cheap-module-source-map' : false, name: isServer ? 'server' : 'client', cache: true, target: isServer ? 'node' : 'web', externals: externalsConfig(dir, isServer), optimization: optimizationConfig({ dir: dir, dev: dev, isServer: isServer, totalPages: totalPages }), recordsPath: _path.default.join(outputPath, 'records.json'), context: dir, // Kept as function to be backwards compatible entry: function () { var _entry = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee() { return _regenerator.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: return _context.abrupt("return", (0, _objectSpread2.default)({}, clientEntries, pagesEntries)); case 1: case "end": return _context.stop(); } } }, _callee, this); })); return function entry() { return _entry.apply(this, arguments); }; }(), output: { path: outputPath, filename: function filename(_ref4) { var chunk = _ref4.chunk; // Use `[name]-[contenthash].js` in production if (!dev && (chunk.name === _constants.CLIENT_STATIC_FILES_RUNTIME_MAIN || chunk.name === _constants.CLIENT_STATIC_FILES_RUNTIME_WEBPACK)) { return chunk.name.replace(/\.js$/, '-[contenthash].js'); } return '[name]'; }, libraryTarget: isServer ? 'commonjs2' : 'jsonp', hotUpdateChunkFilename: 'static/webpack/[id].[hash].hot-update.js', hotUpdateMainFilename: 'static/webpack/[hash].hot-update.json', // This saves chunks with the name given via `import()` chunkFilename: isServer ? "".concat(dev ? '[name]' : '[name].[contenthash]', ".js") : "static/chunks/".concat(dev ? '[name]' : '[name].[contenthash]', ".js"), strictModuleExceptionHandling: true }, performance: { hints: false }, resolve: resolveConfig, resolveLoader: { modules: [_constants.NEXT_PROJECT_ROOT_NODE_MODULES, 'node_modules', _path.default.join(__dirname, 'webpack', 'loaders')].concat((0, _toConsumableArray2.default)(nodePathList)) }, module: { rules: [dev && !isServer && { test: defaultLoaders.hotSelfAccept.options.extensions, include: defaultLoaders.hotSelfAccept.options.include, use: defaultLoaders.hotSelfAccept }, { test: /\.(js|jsx)$/, include: [dir], exclude: /node_modules/, use: defaultLoaders.babel }].filter(Boolean) }, plugins: [// Precompile react / react-dom for development, speeding up webpack dev && !isServer && new _autodllWebpackPlugin.default({ filename: '[name]_[hash].js', path: './static/development/dll', context: dir, entry: { dll: ['react', 'react-dom'] }, config: { mode: webpackMode, resolve: resolveConfig } }), // This plugin makes sure `output.filename` is used for entry chunks new _chunkNamesPlugin.default(), !isServer && new _reactLoadablePlugin.ReactLoadablePlugin({ filename: _constants.REACT_LOADABLE_MANIFEST }), new _webpackbar.default({ name: isServer ? 'server' : 'client' }), dev && !isServer && new _friendlyErrorsWebpackPlugin.default(), new _webpack.default.IgnorePlugin(/(precomputed)/, /node_modules.+(elliptic)/), // This removes prop-types-exact in production, as it's not used there. !dev && new _webpack.default.IgnorePlugin({ checkResource: function checkResource(resource) { return /prop-types-exact/.test(resource); }, checkContext: function checkContext(context) { return context.indexOf(_constants.NEXT_PROJECT_ROOT_DIST) !== -1; } }), // Even though require.cache is server only we have to clear assets from both compilations // This is because the client compilation generates the build manifest that's used on the server side dev && new _nextjsRequireCacheHotReloader.default(), dev && !isServer && new _webpack.default.HotModuleReplacementPlugin(), dev && new _webpack.default.NoEmitOnErrorsPlugin(), dev && new _unlinkFilePlugin.default(), dev && new _caseSensitivePathsWebpackPlugin.default(), // Since on macOS the filesystem is case-insensitive this will make sure your path are case-sensitive dev && new _writeFileWebpackPlugin.default({ exitOnErrors: false, log: false, // required not to cache removed files useHashIndex: false }), // Removes server/client code by minifier new _webpack.default.DefinePlugin({ 'process.browser': (0, _stringify.default)(!isServer) }), // This is used in client/dev-error-overlay/hot-dev-client.js to replace the dist directory !isServer && dev && new _webpack.default.DefinePlugin({ 'process.env.__NEXT_DIST_DIR': (0, _stringify.default)(distDir) }), isServer && new _pagesManifestPlugin.default(), !isServer && new _buildManifestPlugin.default(), !isServer && new _pagesPlugin.default(), isServer && new _nextjsSsrImport.default(), isServer && new _nextjsSsrModuleCache.default({ outputPath: outputPath })].filter(Boolean) }; if (typeof config.webpack === 'function') { webpackConfig = config.webpack(webpackConfig, { dir: dir, dev: dev, isServer: isServer, buildId: buildId, config: config, defaultLoaders: defaultLoaders, totalPages: totalPages }); } // Backwards compat for `main.js` entry key originalEntry = webpackConfig.entry; webpackConfig.entry = /*#__PURE__*/ (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee2() { var entry; return _regenerator.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: _context2.t0 = _objectSpread2.default; _context2.t1 = {}; _context2.next = 4; return originalEntry(); case 4: _context2.t2 = _context2.sent; entry = (0, _context2.t0)(_context2.t1, _context2.t2); // Server compilation doesn't have main.js if (typeof entry['main.js'] !== 'undefined') { entry[_constants.CLIENT_STATIC_FILES_RUNTIME_MAIN] = (0, _toConsumableArray2.default)(entry['main.js']).concat((0, _toConsumableArray2.default)(entry[_constants.CLIENT_STATIC_FILES_RUNTIME_MAIN])); delete entry['main.js']; } return _context2.abrupt("return", entry); case 8: case "end": return _context2.stop(); } } }, _callee2, this); })); return _context3.abrupt("return", webpackConfig); case 17: case "end": return _context3.stop(); } } }, _callee3, this); })); return _getBaseWebpackConfig.apply(this, arguments); }