Open wang1dot0 opened 4 years ago
webpack.base.config.js
const path = require('path'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin'); const NODE_ENV = process.env.NODE_ENV || 'development'; const isProd = NODE_ENV === 'production'; function resolve(dir) { return path.join(__dirname, '..', dir); } const cssLoader = [ { loader: 'css-loader', options: { minimize: isProd }, }, 'postcss-loader', 'less-loader', ]; const webpackCommonPlugins = [ new VueLoaderPlugin(), new MiniCssExtractPlugin({ filename: 'common.[chunkhash].css', }), ...(isProd ? [] : [new FriendlyErrorsPlugin()]), ]; module.exports = { mode: NODE_ENV, devtool: isProd ? false : '#cheap-module-source-map', output: { path: resolve('dist'), publicPath: '/dist/', library: 'CONSOLE', jsonpFunction: 'CONSOLEJsonp', filename: '[name].[chunkhash].js', }, externals: { jquery: 'jQuery', }, resolve: { extensions: ['.webpack.js', '.web.js', '.ts', '.js', '.json', '.vue'], alias: { public: resolve('public'), jquery: resolve('public/js/jquery.min.js'), vue$: 'vue/dist/vue.esm.js', '@': resolve('src'), }, }, module: { noParse: /es6-promise\.js$/, rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { compilerOptions: { preserveWhitespace: false, }, }, }, ], }, performance: { maxEntrypointSize: 300000, hints: isProd ? 'warning' : false, }, plugins: webpackCommonPlugins, };
webpack.client.config.js
const webpack = require('webpack'); const merge = require('webpack-merge'); const base = require('./webpack.base.config'); const VueSSRClientPlugin = require('vue-server-renderer/client-plugin'); const config = merge(base, { entry: { app: './src/entry-client.js', }, resolve: { alias: { 'create-api': './create-api-client.ts', logger: './logger-client.ts', }, }, optimization: { runtimeChunk: { name: 'manifest', }, splitChunks: { chunks: 'initial', cacheGroups: { vendor: { name: 'vendor', test(module) { return ( /node_modules/.test(module.context) && !/\.css$/.test(module.request) ); }, }, }, }, }, plugins: [ new webpack.ProvidePlugin({ $: 'jquery', }), // strip dev-only code in Vue source new webpack.DefinePlugin({ 'process.env.VUE_ENV': '"client"', }), new VueSSRClientPlugin(), ], }); module.exports = config;
webpack.server.config.js
const webpack = require('webpack'); const merge = require('webpack-merge'); const base = require('./webpack.base.config'); const nodeExternals = require('webpack-node-externals'); const VueSSRServerPlugin = require('vue-server-renderer/server-plugin'); module.exports = merge(base, { target: 'node', devtool: '#source-map', entry: './src/entry-server.js', output: { filename: 'server-bundle.js', libraryTarget: 'commonjs2', }, resolve: { alias: { 'create-api': './create-api-server.ts', logger: './logger-server.ts', }, }, // https://webpack.js.org/configuration/externals/#externals // https://github.com/liady/webpack-node-externals externals: nodeExternals({ // do not externalize CSS files in case we need to import it from a dep whitelist: /\.css$|vue-echarts/, }), plugins: [ new webpack.DefinePlugin({ 'process.env.VUE_ENV': '"server"', }), new VueSSRServerPlugin(), ], });
setup-dev-server.js
const path = require('path'); const webpack = require('webpack'); const MFS = require('memory-fs'); const clientConfig = require('./webpack.client.config'); const serverConfig = require('./webpack.server.config'); const readFile = (fs, file) => { try { return fs.readFileSync(path.join(clientConfig.output.path, file), 'utf-8'); } catch (e) {} }; module.exports = function setupDevServer(app, cb) { let bundle, clientManifest; let resolve; const readyPromise = new Promise(r => { resolve = r; }); const ready = (...args) => { resolve(); cb(...args); }; // modify client config to work with hot middleware clientConfig.entry.app = ['webpack-hot-middleware/client', clientConfig.entry.app]; clientConfig.output.filename = '[name].js'; clientConfig.plugins.push(new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin()); // dev middleware const clientCompiler = webpack(clientConfig); const devMiddleware = require('webpack-dev-middleware')(clientCompiler, { publicPath: clientConfig.output.publicPath, noInfo: true, }); app.use(devMiddleware); clientCompiler.plugin('done', stats => { stats = stats.toJson(); stats.errors.forEach(err => console.error(err)); stats.warnings.forEach(err => console.warn(err)); if (stats.errors.length) return; clientManifest = JSON.parse(readFile(devMiddleware.fileSystem, 'vue-ssr-client-manifest.json')); if (bundle) { ready(bundle, { clientManifest, inject: false, }); } }); // hot middleware app.use(require('webpack-hot-middleware')(clientCompiler)); // watch and update server renderer const serverCompiler = webpack(serverConfig); const mfs = new MFS(); serverCompiler.outputFileSystem = mfs; serverCompiler.watch({}, (err, stats) => { if (err) throw err; stats = stats.toJson(); if (stats.errors.length) return; // read bundle generated by vue-ssr-webpack-plugin bundle = JSON.parse(readFile(mfs, 'vue-ssr-server-bundle.json')); if (clientManifest) { ready(bundle, { clientManifest, inject: false, }); } }); return readyPromise; };
webpack.base.config.js
webpack.client.config.js
webpack.server.config.js
setup-dev-server.js