mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			278 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			278 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { basename, resolve } from 'path';
 | 
						|
import { cacheLoader, getExposeLoaders } from './webpack-helpers';
 | 
						|
import BundleTracker from 'webpack4-bundle-tracker';
 | 
						|
import CleanCss from 'clean-css';
 | 
						|
import DebugRequirePlugin from './debug-require-webpack-plugin';
 | 
						|
import HtmlWebpackPlugin from 'html-webpack-plugin';
 | 
						|
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
 | 
						|
import OptimizeCssAssetsPlugin from 'optimize-css-assets-webpack-plugin';
 | 
						|
import TerserPlugin from 'terser-webpack-plugin';
 | 
						|
// The devServer member of webpack.Configuration is managed by the
 | 
						|
// webpack-dev-server package. We are only importing the type here.
 | 
						|
import _webpackDevServer from 'webpack-dev-server';
 | 
						|
import webpack from 'webpack';
 | 
						|
 | 
						|
const assets: { [name: string]: string[] } = require('./webpack.assets.json');
 | 
						|
 | 
						|
export default (env?: string): webpack.Configuration[] => {
 | 
						|
    const production: boolean = env === "production";
 | 
						|
    const config: webpack.Configuration = {
 | 
						|
        name: "frontend",
 | 
						|
        mode: production ? "production" : "development",
 | 
						|
        context: resolve(__dirname, "../"),
 | 
						|
        entry: assets,
 | 
						|
        module: {
 | 
						|
            rules: [
 | 
						|
                // Generate webfont
 | 
						|
                {
 | 
						|
                    test: /\.font\.js$/,
 | 
						|
                    use: [
 | 
						|
                        MiniCssExtractPlugin.loader,
 | 
						|
                        {
 | 
						|
                            loader: 'css-loader',
 | 
						|
                            options: {
 | 
						|
                                url: false,  // webfonts-loader generates public relative URLs
 | 
						|
                            },
 | 
						|
                        },
 | 
						|
                        {
 | 
						|
                            loader: 'webfonts-loader',
 | 
						|
                            options: {
 | 
						|
                                fileName: production ? 'files/[fontname].[chunkhash].[ext]' : 'files/[fontname].[ext]',
 | 
						|
                                publicPath: '',
 | 
						|
                            },
 | 
						|
                        },
 | 
						|
                    ],
 | 
						|
                },
 | 
						|
                // Transpile .js and .ts files with Babel
 | 
						|
                {
 | 
						|
                    test: /\.(js|ts)$/,
 | 
						|
                    include: [
 | 
						|
                        resolve(__dirname, '../static/shared/js'),
 | 
						|
                        resolve(__dirname, '../static/js'),
 | 
						|
                    ],
 | 
						|
                    use: [cacheLoader, 'babel-loader'],
 | 
						|
                },
 | 
						|
                // Uses script-loader on minified files so we don't change global variables in them.
 | 
						|
                // Also has the effect of making processing these files fast
 | 
						|
                // Currently the source maps don't work with these so use unminified files
 | 
						|
                // if debugging is required.
 | 
						|
                {
 | 
						|
                    // We dont want to match admin.js
 | 
						|
                    test: /(\.min|min\.|zxcvbn)\.js/,
 | 
						|
                    use: [cacheLoader, 'script-loader'],
 | 
						|
                },
 | 
						|
                // regular css files
 | 
						|
                {
 | 
						|
                    test: /\.css$/,
 | 
						|
                    use: [
 | 
						|
                        {
 | 
						|
                            loader: MiniCssExtractPlugin.loader,
 | 
						|
                            options: {
 | 
						|
                                hmr: !production,
 | 
						|
                            },
 | 
						|
                        },
 | 
						|
                        cacheLoader,
 | 
						|
                        {
 | 
						|
                            loader: 'css-loader',
 | 
						|
                            options: {
 | 
						|
                                sourceMap: true,
 | 
						|
                            },
 | 
						|
                        },
 | 
						|
                    ],
 | 
						|
                },
 | 
						|
                // scss loader
 | 
						|
                {
 | 
						|
                    test: /\.scss$/,
 | 
						|
                    include: resolve(__dirname, '../static/styles'),
 | 
						|
                    use: [
 | 
						|
                        {
 | 
						|
                            loader: MiniCssExtractPlugin.loader,
 | 
						|
                            options: {
 | 
						|
                                hmr: !production,
 | 
						|
                            },
 | 
						|
                        },
 | 
						|
                        cacheLoader,
 | 
						|
                        {
 | 
						|
                            loader: 'css-loader',
 | 
						|
                            options: {
 | 
						|
                                importLoaders: 1,
 | 
						|
                                sourceMap: true,
 | 
						|
                            },
 | 
						|
                        },
 | 
						|
                        {
 | 
						|
                            loader: 'postcss-loader',
 | 
						|
                            options: {
 | 
						|
                                sourceMap: true,
 | 
						|
                            },
 | 
						|
                        },
 | 
						|
                    ],
 | 
						|
                },
 | 
						|
                {
 | 
						|
                    test: /\.hbs$/,
 | 
						|
                    use: [
 | 
						|
                        cacheLoader,
 | 
						|
                        {
 | 
						|
                            loader: 'handlebars-loader',
 | 
						|
                            options: {
 | 
						|
                                // Tell webpack not to explicitly require these.
 | 
						|
                                knownHelpers: [
 | 
						|
                                    'if', 'unless', 'each', 'with',
 | 
						|
                                    // The ones below are defined in static/js/templates.js
 | 
						|
                                    'plural', 'eq', 'and', 'or', 'not',
 | 
						|
                                    't', 'tr', 'rendered_markdown',
 | 
						|
                                ],
 | 
						|
                                preventIndent: true,
 | 
						|
                            },
 | 
						|
                        },
 | 
						|
                    ],
 | 
						|
                },
 | 
						|
                // load fonts and files
 | 
						|
                {
 | 
						|
                    test: /\.(woff(2)?|ttf|eot|svg|otf|png)$/,
 | 
						|
                    use: [{
 | 
						|
                        loader: 'file-loader',
 | 
						|
                        options: {
 | 
						|
                            name: production ? '[name].[hash].[ext]' : '[path][name].[ext]',
 | 
						|
                            outputPath: 'files/',
 | 
						|
                        },
 | 
						|
                    }],
 | 
						|
                },
 | 
						|
            ],
 | 
						|
        },
 | 
						|
        output: {
 | 
						|
            path: resolve(__dirname, '../static/webpack-bundles'),
 | 
						|
            filename: production ? '[name].[contenthash].js' : '[name].js',
 | 
						|
            chunkFilename: production ? '[contenthash].js' : '[id].js',
 | 
						|
        },
 | 
						|
        resolve: {
 | 
						|
            extensions: [".ts", ".js"],
 | 
						|
        },
 | 
						|
        // We prefer cheap-module-source-map over any eval-** options
 | 
						|
        // because the eval-options currently don't support being
 | 
						|
        // source mapped in error stack traces
 | 
						|
        // We prefer it over eval since eval has trouble setting
 | 
						|
        // breakpoints in chrome.
 | 
						|
        devtool: production ? 'source-map' : 'cheap-module-source-map',
 | 
						|
        optimization: {
 | 
						|
            minimizer: [
 | 
						|
                // Based on a comment in NMFR/optimize-css-assets-webpack-plugin#10.
 | 
						|
                // Can be simplified when NMFR/optimize-css-assets-webpack-plugin#87
 | 
						|
                // is fixed.
 | 
						|
                new OptimizeCssAssetsPlugin({
 | 
						|
                    cssProcessor: {
 | 
						|
                        async process(css, options: any) {
 | 
						|
                            const filename = basename(options.to);
 | 
						|
                            const result = await new CleanCss(options).minify({
 | 
						|
                                [filename]: {
 | 
						|
                                    styles: css,
 | 
						|
                                    sourceMap: options.map.prev,
 | 
						|
                                },
 | 
						|
                            });
 | 
						|
                            for (const warning of result.warnings) {
 | 
						|
                                console.warn(warning);
 | 
						|
                            }
 | 
						|
                            return {
 | 
						|
                                css: result.styles + `\n/*# sourceMappingURL=${filename}.map */`,
 | 
						|
                                map: result.sourceMap,
 | 
						|
                            };
 | 
						|
                        },
 | 
						|
                    },
 | 
						|
                    cssProcessorOptions: {
 | 
						|
                        map: {},
 | 
						|
                        returnPromise: true,
 | 
						|
                        sourceMap: true,
 | 
						|
                        sourceMapInlineSources: true,
 | 
						|
                    },
 | 
						|
                }),
 | 
						|
                new TerserPlugin({
 | 
						|
                    cache: true,
 | 
						|
                    parallel: true,
 | 
						|
                    sourceMap: true,
 | 
						|
                }),
 | 
						|
            ],
 | 
						|
            splitChunks: {
 | 
						|
                chunks: "all",
 | 
						|
                // webpack/examples/many-pages suggests 20 requests for HTTP/2
 | 
						|
                maxAsyncRequests: 20,
 | 
						|
                maxInitialRequests: 20,
 | 
						|
            },
 | 
						|
        },
 | 
						|
        plugins: [
 | 
						|
            new DebugRequirePlugin(),
 | 
						|
            new BundleTracker({
 | 
						|
                filename: production
 | 
						|
                    ? 'webpack-stats-production.json'
 | 
						|
                    : 'var/webpack-stats-dev.json',
 | 
						|
            }),
 | 
						|
            ...production
 | 
						|
                ? []
 | 
						|
                : [
 | 
						|
                    // Better logging from console for hot reload
 | 
						|
                    new webpack.NamedModulesPlugin(),
 | 
						|
                    // script-loader should load sourceURL in dev
 | 
						|
                    new webpack.LoaderOptionsPlugin({debug: true}),
 | 
						|
                ],
 | 
						|
            // Extract CSS from files
 | 
						|
            new MiniCssExtractPlugin({
 | 
						|
                filename: production ? "[name].[contenthash].css" : "[name].css",
 | 
						|
                chunkFilename: production ? "[contenthash].css" : "[id].css",
 | 
						|
            }),
 | 
						|
            new HtmlWebpackPlugin({
 | 
						|
                filename: "5xx.html",
 | 
						|
                template: "static/html/5xx.html",
 | 
						|
                chunks: ["error-styles"],
 | 
						|
            }),
 | 
						|
        ],
 | 
						|
    };
 | 
						|
 | 
						|
    // Expose Global variables for third party libraries to webpack modules
 | 
						|
    // Use the unminified versions of jquery and underscore so that
 | 
						|
    // Good error messages show up in production and development in the source maps
 | 
						|
    const exposeOptions = [
 | 
						|
        { path: "./debug-require.js", name: "require" },
 | 
						|
        { path: "blueimp-md5/js/md5.js" },
 | 
						|
        { path: "clipboard/dist/clipboard.js", name: "ClipboardJS" },
 | 
						|
        { path: "xdate/src/xdate.js", name: "XDate" },
 | 
						|
        { path: "../static/third/marked/lib/marked.js" },
 | 
						|
        { path: "../static/js/debug.js" },
 | 
						|
        { path: "../static/js/blueslip.js" },
 | 
						|
        { path: "../static/js/common.js" },
 | 
						|
        { path: "jquery/dist/jquery.js", name: ['$', 'jQuery'] },
 | 
						|
        { path: "underscore/underscore.js", name: '_' },
 | 
						|
        { path: "handlebars/dist/cjs/handlebars.runtime.js", name: 'Handlebars' },
 | 
						|
        { path: "sortablejs/Sortable.js"},
 | 
						|
        { path: "winchan/winchan.js", name: 'WinChan'},
 | 
						|
    ];
 | 
						|
    config.module.rules.unshift(...getExposeLoaders(exposeOptions));
 | 
						|
 | 
						|
    if (!production) {
 | 
						|
        // Out JS debugging tools
 | 
						|
        for (const name of Object.keys(config.entry)) {
 | 
						|
            assets[name].push('./static/js/debug.js');
 | 
						|
        }
 | 
						|
        config.devServer = {
 | 
						|
            clientLogLevel: "error",
 | 
						|
            headers: {
 | 
						|
                "Access-Control-Allow-Origin": "*",
 | 
						|
            },
 | 
						|
            publicPath: "/webpack/",
 | 
						|
            stats: "errors-only",
 | 
						|
        };
 | 
						|
    }
 | 
						|
 | 
						|
    const serverConfig: webpack.Configuration = {
 | 
						|
        mode: production ? "production" : "development",
 | 
						|
        target: "node",
 | 
						|
        context: resolve(__dirname, "../"),
 | 
						|
        entry: {
 | 
						|
            "katex-cli": "shebang-loader!katex/cli",
 | 
						|
        },
 | 
						|
        output: {
 | 
						|
            path: resolve(__dirname, "../static/webpack-bundles"),
 | 
						|
            filename: "[name].js",
 | 
						|
        },
 | 
						|
    };
 | 
						|
 | 
						|
    return [config, serverConfig];
 | 
						|
};
 |