浏览代码

Split webpack dev config into dev and hot

Motivation:

* too many conditionals for config, better to be explicit
* different priorities: faster build for hot mode
* working SCSS sources for styles in hot mode

The biggest differences:

* removed linter from TS loader in hot (should be editor or precommit
 or responsibility)
* simplified styles loading
* hot needs more extensions to resolve
* removed commons chunking for hot
* removed devServer from dev

Reduced HMR time from 8s to 4s on my machine.
David Kaltschmidt 7 年之前
父节点
当前提交
ebe8e62bd5
共有 3 个文件被更改,包括 102 次插入63 次删除
  1. 2 2
      package.json
  2. 9 61
      scripts/webpack/webpack.dev.js
  3. 91 0
      scripts/webpack/webpack.hot.js

+ 2 - 2
package.json

@@ -105,7 +105,7 @@
   },
   },
   "scripts": {
   "scripts": {
     "dev": "webpack --progress --colors --config scripts/webpack/webpack.dev.js",
     "dev": "webpack --progress --colors --config scripts/webpack/webpack.dev.js",
-    "start": "webpack-dev-server --progress --colors --config scripts/webpack/webpack.dev.js",
+    "start": "webpack-dev-server --progress --colors --config scripts/webpack/webpack.hot.js",
     "watch": "webpack --progress --colors --watch --config scripts/webpack/webpack.dev.js",
     "watch": "webpack --progress --colors --watch --config scripts/webpack/webpack.dev.js",
     "build": "grunt build",
     "build": "grunt build",
     "test": "grunt test",
     "test": "grunt test",
@@ -183,4 +183,4 @@
   "resolutions": {
   "resolutions": {
     "caniuse-db": "1.0.30000772"
     "caniuse-db": "1.0.30000772"
   }
   }
-}
+}

+ 9 - 61
scripts/webpack/webpack.dev.js

@@ -5,61 +5,29 @@ const common = require('./webpack.common.js');
 const path = require('path');
 const path = require('path');
 const webpack = require('webpack');
 const webpack = require('webpack');
 const HtmlWebpackPlugin = require("html-webpack-plugin");
 const HtmlWebpackPlugin = require("html-webpack-plugin");
-const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin');
 const ExtractTextPlugin = require("extract-text-webpack-plugin");
 const ExtractTextPlugin = require("extract-text-webpack-plugin");
 const CleanWebpackPlugin = require('clean-webpack-plugin');
 const CleanWebpackPlugin = require('clean-webpack-plugin');
 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 
 
-const TARGET = process.env.npm_lifecycle_event;
-const HOT = TARGET === 'start';
-
 const extractSass = new ExtractTextPlugin({
 const extractSass = new ExtractTextPlugin({
-  filename: "grafana.[name].css",
-  disable: HOT
+  filename: "grafana.[name].css"
 });
 });
 
 
-const entries = HOT ? {
-  app: [
-    'webpack-dev-server/client?http://localhost:3333',
-    './public/app/dev.ts',
-  ],
-  vendor: require('./dependencies'),
-} : {
+module.exports = merge(common, {
+  devtool: "cheap-module-source-map",
+
+  entry: {
     app: './public/app/index.ts',
     app: './public/app/index.ts',
     dark: './public/sass/grafana.dark.scss',
     dark: './public/sass/grafana.dark.scss',
     light: './public/sass/grafana.light.scss',
     light: './public/sass/grafana.light.scss',
     vendor: require('./dependencies'),
     vendor: require('./dependencies'),
-  };
+  },
 
 
-const output = HOT ? {
-  path: path.resolve(__dirname, '../../public/build'),
-  filename: '[name].[hash].js',
-  publicPath: "/public/build/",
-} : {
+  output: {
     path: path.resolve(__dirname, '../../public/build'),
     path: path.resolve(__dirname, '../../public/build'),
     filename: '[name].[hash].js',
     filename: '[name].[hash].js',
     // Keep publicPath relative for host.com/grafana/ deployments
     // Keep publicPath relative for host.com/grafana/ deployments
     publicPath: "public/build/",
     publicPath: "public/build/",
-  };
-
-module.exports = merge(common, {
-  devtool: "cheap-module-source-map",
-
-  entry: entries,
-
-  output: output,
-
-  resolve: {
-    extensions: ['.scss', '.ts', '.tsx', '.es6', '.js', '.json', '.svg', '.woff2', '.png'],
-  },
-
-  devServer: {
-    publicPath: '/public/build/',
-    hot: HOT,
-    port: 3333,
-    proxy: {
-      '!/public/build': 'http://localhost:3000'
-    }
   },
   },
 
 
   module: {
   module: {
@@ -83,33 +51,16 @@ module.exports = merge(common, {
           loader: 'awesome-typescript-loader',
           loader: 'awesome-typescript-loader',
           options: {
           options: {
             useCache: true,
             useCache: true,
-            useBabel: HOT,
-            babelOptions: {
-              babelrc: false,
-              plugins: [
-                'syntax-dynamic-import',
-                'react-hot-loader/babel'
-              ]
-            }
           },
           },
         }
         }
       },
       },
       require('./sass.rule.js')({
       require('./sass.rule.js')({
-        sourceMap: true, minimize: false, preserveUrl: HOT
+        sourceMap: true, minimize: false, preserveUrl: false
       }, extractSass),
       }, extractSass),
       {
       {
-        test: /\.(ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
+        test: /\.(png|jpg|gif|ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
         loader: 'file-loader'
         loader: 'file-loader'
       },
       },
-      {
-        test: /\.(png|jpg|gif)$/,
-        use: [
-          {
-            loader: 'file-loader',
-            options: {}
-          }
-        ]
-      },
     ]
     ]
   },
   },
 
 
@@ -121,13 +72,10 @@ module.exports = merge(common, {
       template: path.resolve(__dirname, '../../public/views/index.template.html'),
       template: path.resolve(__dirname, '../../public/views/index.template.html'),
       inject: 'body',
       inject: 'body',
       chunks: ['manifest', 'vendor', 'app'],
       chunks: ['manifest', 'vendor', 'app'],
-      alwaysWriteToDisk: HOT
     }),
     }),
-    new HtmlWebpackHarddiskPlugin(),
     new webpack.NamedModulesPlugin(),
     new webpack.NamedModulesPlugin(),
     new webpack.HotModuleReplacementPlugin(),
     new webpack.HotModuleReplacementPlugin(),
     new webpack.DefinePlugin({
     new webpack.DefinePlugin({
-      'GRAFANA_THEME': JSON.stringify(process.env.GRAFANA_THEME || 'dark'),
       'process.env': {
       'process.env': {
         'NODE_ENV': JSON.stringify('development')
         'NODE_ENV': JSON.stringify('development')
       }
       }

+ 91 - 0
scripts/webpack/webpack.hot.js

@@ -0,0 +1,91 @@
+'use strict';
+
+const merge = require('webpack-merge');
+const common = require('./webpack.common.js');
+const path = require('path');
+const webpack = require('webpack');
+const HtmlWebpackPlugin = require("html-webpack-plugin");
+const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin');
+const CleanWebpackPlugin = require('clean-webpack-plugin');
+
+module.exports = merge(common, {
+  entry: {
+    app: [
+      'webpack-dev-server/client?http://localhost:3333',
+      './public/app/dev.ts',
+    ],
+  },
+
+  output: {
+    path: path.resolve(__dirname, '../../public/build'),
+    filename: '[name].[hash].js',
+    publicPath: "/public/build/",
+  },
+
+  resolve: {
+    extensions: ['.scss', '.ts', '.tsx', '.es6', '.js', '.json', '.svg', '.woff2', '.png'],
+  },
+
+  devServer: {
+    publicPath: '/public/build/',
+    hot: true,
+    port: 3333,
+    proxy: {
+      '!/public/build': 'http://localhost:3000'
+    }
+  },
+
+  module: {
+    rules: [
+      {
+        test: /\.tsx?$/,
+        exclude: /node_modules/,
+        use: {
+          loader: 'awesome-typescript-loader',
+          options: {
+            useCache: true,
+            useBabel: true,
+            babelOptions: {
+              babelrc: false,
+              plugins: [
+                'syntax-dynamic-import',
+                'react-hot-loader/babel'
+              ]
+            }
+          },
+        }
+      },
+      {
+        test: /\.scss$/,
+        use: [
+          "style-loader", // creates style nodes from JS strings
+          "css-loader", // translates CSS into CommonJS
+          "sass-loader" // compiles Sass to CSS
+        ]
+      },
+      {
+        test: /\.(png|jpg|gif|ttf|eot|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/,
+        loader: 'file-loader'
+      },
+    ]
+  },
+
+  plugins: [
+    new CleanWebpackPlugin('../public/build', { allowExternal: true }),
+    new HtmlWebpackPlugin({
+      filename: path.resolve(__dirname, '../../public/views/index.html'),
+      template: path.resolve(__dirname, '../../public/views/index.template.html'),
+      inject: 'body',
+      alwaysWriteToDisk: true
+    }),
+    new HtmlWebpackHarddiskPlugin(),
+    new webpack.NamedModulesPlugin(),
+    new webpack.HotModuleReplacementPlugin(),
+    new webpack.DefinePlugin({
+      'GRAFANA_THEME': JSON.stringify(process.env.GRAFANA_THEME || 'dark'),
+      'process.env': {
+        'NODE_ENV': JSON.stringify('development')
+      }
+    }),
+  ]
+});