nakarte

Source code of https://map.sikmir.ru (fork)
git clone git://git.sikmir.ru/nakarte
Log | Files | Refs | LICENSE

webpack.config.js (5495B)


      1 'use strict';
      2 
      3 const {CleanWebpackPlugin} = require('clean-webpack-plugin');
      4 const CopyWebpackPlugin = require('copy-webpack-plugin');
      5 const HtmlWebpackPlugin = require('html-webpack-plugin');
      6 const MiniCssExtractPlugin = require('mini-css-extract-plugin');
      7 const StyleLintPlugin = require('stylelint-webpack-plugin');
      8 const TerserPlugin = require('terser-webpack-plugin');
      9 const Webpack = require('webpack');
     10 
     11 const paths = require('./paths');
     12 
     13 const errorExitStatus = 1;
     14 
     15 const envs = {
     16     production: true,
     17     development: true,
     18     testing: true,
     19 };
     20 
     21 const mode = process.env.NODE_ENV;
     22 
     23 if (!envs[mode]) {
     24     console.log(`NODE_ENV has invalid value "${mode}"`);
     25     process.exit(errorExitStatus);
     26 }
     27 
     28 const isProduction = mode === 'production';
     29 const isDevelopment = mode === 'development';
     30 const isTesting = mode === 'testing';
     31 
     32 const productionOutput = {
     33     path: paths.appBuild,
     34     filename: 'static/js/[name].[contenthash:8].js',
     35 };
     36 
     37 const babelConfig = {
     38     presets: [
     39         [
     40             '@babel/preset-env',
     41             {
     42                 useBuiltIns: 'usage',
     43                 corejs: {version: '3.8', proposals: true},
     44                 modules: 'commonjs',
     45                 exclude: ['proposal-dynamic-import'],
     46             },
     47         ],
     48     ],
     49     overrides: [
     50         {
     51             test: './src/vendored/github.com/augustl/js-unzip/js-unzip.js',
     52             sourceType: 'script',
     53         },
     54     ],
     55 
     56     plugins: [
     57         '@babel/plugin-syntax-dynamic-import',
     58         '@babel/plugin-proposal-class-properties',
     59         '@babel/plugin-proposal-optional-chaining',
     60         '@babel/plugin-proposal-nullish-coalescing-operator',
     61         ...(isTesting ? ['babel-plugin-rewire'] : []),
     62     ],
     63 };
     64 
     65 const sourceMapOption = {
     66     filename: '[file].map',
     67     columns: isProduction,
     68     exclude: /mapillary/u,
     69 };
     70 
     71 const DevToolPlugin = isProduction ? Webpack.SourceMapDevToolPlugin : Webpack.EvalSourceMapDevToolPlugin;
     72 
     73 const plugins = [
     74     ...(isProduction ? [new CleanWebpackPlugin()] : []),
     75     ...(isProduction ? [new CopyWebpackPlugin({patterns: [{from: paths.appPublic, to: ''}]})] : []),
     76     new HtmlWebpackPlugin({
     77         template: paths.appIndexHtml,
     78         minify: false,
     79     }),
     80     ...(isProduction || isDevelopment
     81         ? [
     82               new MiniCssExtractPlugin({
     83                   filename: 'static/css/[name].[contenthash:8].css',
     84               }),
     85           ]
     86         : []),
     87     new Webpack.DefinePlugin({
     88         NODE_ENV: JSON.stringify(mode),
     89         RELEASE_VER: JSON.stringify(process.env.RELEASE_VER || 'local devel'),
     90     }),
     91     ...(isProduction || isDevelopment
     92         ? [
     93               new StyleLintPlugin({
     94                   config: {extends: 'stylelint-config-recommended'},
     95                   files: ['src/**/*.css', 'vendored/**/*.css'],
     96                   emitWarning: isDevelopment,
     97                   emitError: isProduction,
     98               }),
     99           ]
    100         : []),
    101     new DevToolPlugin(sourceMapOption),
    102 ];
    103 
    104 const productionCSSLoader = [
    105     MiniCssExtractPlugin.loader,
    106     {loader: 'css-loader', options: {importLoaders: 1}},
    107     {
    108         loader: 'postcss-loader',
    109         options: {
    110             ident: 'postcss',
    111             plugins: () => [require('postcss-import')(), require('postcss-preset-env')(), require('cssnano')()],
    112         },
    113     },
    114 ];
    115 
    116 const developmentCSSLoader = ['style-loader', {loader: 'css-loader', options: {importLoaders: 1}}];
    117 
    118 const loaders = [
    119     {
    120         test: /\.mjs$/u,
    121         include: /node_modules/u,
    122         type: 'javascript/auto',
    123     },
    124     {
    125         test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/u,
    126         type: 'asset/inline',
    127     },
    128     {
    129         test: /\.(html)(\?.*)?$/u,
    130         loader: 'raw-loader',
    131     },
    132     {
    133         test: /\.csv$/u,
    134         loader: 'csv-loader',
    135         options: {
    136             dynamicTyping: true,
    137             header: true,
    138             skipEmptyLines: true,
    139         },
    140     },
    141 
    142     ...(isProduction || isDevelopment
    143         ? [
    144               {
    145                   test: /\.js$/u,
    146                   include: paths.appSrc,
    147                   enforce: 'pre',
    148                   loader: 'eslint-loader',
    149                   options: {
    150                       emitWarning: !isProduction,
    151                   },
    152               },
    153           ]
    154         : []),
    155 
    156     {
    157         test: /\.js$/u,
    158         exclude: isProduction ? [/node_modules\/core-js/u, /node_modules\/webpack/u] : /node_modules/u,
    159         use: [
    160             {
    161                 loader: 'babel-loader',
    162                 options: babelConfig,
    163             },
    164         ],
    165         type: 'javascript/auto',
    166     },
    167 
    168     {
    169         test: /\.s?css/iu,
    170         use: isProduction ? productionCSSLoader : developmentCSSLoader,
    171     },
    172 ];
    173 
    174 module.exports = {
    175     mode: isProduction ? 'production' : 'development',
    176     devtool: false,
    177     stats: 'errors-warnings',
    178     bail: isProduction || isTesting,
    179     devServer: {
    180         client: {
    181             overlay: false,
    182         },
    183     },
    184 
    185     entry: {
    186         app: paths.appIndexJs,
    187     },
    188 
    189     optimization: {
    190         splitChunks: {
    191             chunks: 'all',
    192         },
    193         runtimeChunk: 'single',
    194         minimizer: [
    195             new TerserPlugin({
    196                 parallel: true,
    197                 exclude: /node_modules\/mapillary/u,
    198             }),
    199         ],
    200     },
    201 
    202     resolve: {
    203         alias: {
    204             '~': paths.appSrc,
    205         },
    206     },
    207 
    208     output: isProduction ? productionOutput : {},
    209     plugins: plugins,
    210     module: {
    211         rules: loaders,
    212     },
    213 };