serlina
Version:
A progressive React serverside-rendering framework
171 lines (170 loc) • 5.99 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("push-if");
const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const merge = require('webpack-merge');
const AssetsWebpackPlugin = require('assets-webpack-plugin');
const WebpackBar = require('webpackbar');
const WFP = require('write-file-webpack-plugin');
const nodeExternals = require('webpack-node-externals');
const fs = require("fs");
const SerlinaLoader = require.resolve('./serlina-loader');
const noop = () => { };
exports.default = (options) => {
const { customConfig, baseDir, outputPath, publicPath, serlinaConfig, dev, pages, __testing, onFinishedClientSideCompilation, } = options;
const entries = {};
pages.forEach(page => {
entries[page.split('.').slice(0, -1).join('.')] = './pages/' + page;
});
const assetsWebpackPlugin = new AssetsWebpackPlugin({
path: outputPath,
filename: 'assetsmap.json',
fullPath: false
});
const babelLoader = {
loader: 'babel-loader',
options: {
root: baseDir,
configFile: fs.existsSync(path.resolve(baseDir, './babel.config.js')) ? path.resolve(baseDir, './babel.config.js') : path.resolve(__dirname, '../../babel.config.js')
}
};
// struct webpack config
let defaultCommonConfig = {
mode: dev ? 'development' : 'production',
context: baseDir,
devtool: false,
resolve: {
extensions: [".ts", ".tsx", ".js"],
modules: [
'node_modules',
path.resolve(__dirname, '../../node_modules'),
]
},
resolveLoader: {
modules: [
path.resolve(__dirname, '../../node_modules'),
'node_modules',
]
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules)/,
use: [
babelLoader
]
},
{
test: /\.tsx?$/,
exclude: /(node_modules)/,
use: [
babelLoader,
{
loader: 'ts-loader',
options: {
configFile: path.resolve(baseDir, './tsconfig.json')
}
}
]
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { importLoaders: 1 } }
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: dev ? '[name].css' : '[name]-[chunkhash].css'
}),
]
.pushIf(dev, new webpack.NamedModulesPlugin())
};
const passedOptions = {
miniCSSLoader: MiniCssExtractPlugin.loader,
dev,
merge: merge.smart,
__testing: __testing,
baseDir
};
const clientSideConfig = customConfig ? merge.smart(customConfig(webpack, Object.assign({}, passedOptions, { compileEnv: 'client' })), defaultCommonConfig) : defaultCommonConfig;
const serverSideConfig = customConfig ? merge.smart(customConfig(webpack, Object.assign({}, passedOptions, { compileEnv: 'server' })), defaultCommonConfig) : defaultCommonConfig;
// don't use custom externals in server side code
delete serverSideConfig['externals'];
const clientSide = merge.smart({
entry: Object.assign({}, entries, { '_SERLINA_MAIN': path.resolve(__dirname, '../client/render') }),
externals: {
react: 'React',
'react-dom': 'ReactDOM'
},
target: 'web',
output: {
filename: dev ? '[name].js' : '[name]-[chunkhash].js',
path: outputPath,
publicPath,
library: '__serlina',
globalObject: 'this',
libraryTarget: 'umd',
hotUpdateChunkFilename: 'hot/hot-update.js',
hotUpdateMainFilename: 'hot/hot-update.json'
},
plugins: [
new WebpackBar({
name: 'client side',
minimal: !dev,
color: 'green',
done: onFinishedClientSideCompilation || noop,
})
]
.pushIf(!dev, assetsWebpackPlugin),
}, clientSideConfig);
const whitelist = [/\.(?!(?:jsx?|json)$).{1,5}$/i];
const serverSide = merge.smart({
entry: entries,
target: 'node',
externals: [nodeExternals({
whitelist: serlinaConfig.nodeExternalsWhitelist ? whitelist.concat(serlinaConfig.nodeExternalsWhitelist) : whitelist
})],
output: {
filename: '[name].cmd.js',
path: outputPath,
publicPath,
libraryTarget: 'commonjs2'
},
plugins: [
new WFP(),
new WebpackBar({
name: 'server side',
color: 'orange',
minimal: !dev,
done: onFinishedClientSideCompilation || noop
})
]
}, serverSideConfig);
const vendors = merge.smart({
entry: {
'_SERLINA_VENDOR': [
require.resolve('@babel/polyfill'),
path.resolve(__dirname, '../client/common'),
],
},
output: {
filename: dev ? '[name].js' : '[name]-[chunkhash].js',
path: outputPath,
publicPath,
},
plugins: []
.pushIf(!dev, assetsWebpackPlugin)
}, clientSideConfig);
return [
serverSide,
clientSide,
vendors
];
};