Yuki Takei 7 tahun lalu
induk
melakukan
c333e92f7f

+ 41 - 31
config/webpack.common.js

@@ -8,17 +8,17 @@ const helpers = require('./helpers');
 /*
 /*
  * Webpack Plugins
  * Webpack Plugins
  */
  */
-const AssetsPlugin = require('assets-webpack-plugin');
-const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
+const WebpackAssetsManifest = require('webpack-assets-manifest');
 
 
 /*
 /*
  * Webpack configuration
  * Webpack configuration
  *
  *
  * See: http://webpack.github.io/docs/configuration.html#cli
  * See: http://webpack.github.io/docs/configuration.html#cli
  */
  */
-module.exports = function(options) {
+module.exports = (options) => {
   return {
   return {
-    entry: {
+    mode: options.mode,
+    entry: Object.assign({
       'app':                  './resource/js/app',
       'app':                  './resource/js/app',
       'legacy':               './resource/js/legacy/crowi',
       'legacy':               './resource/js/legacy/crowi',
       'legacy-form':          './resource/js/legacy/crowi-form',
       'legacy-form':          './resource/js/legacy/crowi-form',
@@ -26,14 +26,21 @@ module.exports = function(options) {
       'legacy-presentation':  './resource/js/legacy/crowi-presentation',
       'legacy-presentation':  './resource/js/legacy/crowi-presentation',
       'plugin':               './resource/js/plugin',
       'plugin':               './resource/js/plugin',
       'style':                './resource/styles/scss/style.scss',
       'style':                './resource/styles/scss/style.scss',
+      'style-presentation':   './resource/styles/scss/style-presentation.scss',
+      // themes
       'style-theme-default':  './resource/styles/scss/theme/default.scss',
       'style-theme-default':  './resource/styles/scss/theme/default.scss',
       'style-theme-default-dark':  './resource/styles/scss/theme/default-dark.scss',
       'style-theme-default-dark':  './resource/styles/scss/theme/default-dark.scss',
       'style-theme-nature':   './resource/styles/scss/theme/nature.scss',
       'style-theme-nature':   './resource/styles/scss/theme/nature.scss',
       'style-theme-mono-blue':   './resource/styles/scss/theme/mono-blue.scss',
       'style-theme-mono-blue':   './resource/styles/scss/theme/mono-blue.scss',
       'style-theme-future': './resource/styles/scss/theme/future.scss',
       'style-theme-future': './resource/styles/scss/theme/future.scss',
       'style-theme-blue-night': './resource/styles/scss/theme/blue-night.scss',
       'style-theme-blue-night': './resource/styles/scss/theme/blue-night.scss',
-      'style-presentation':   './resource/styles/scss/style-presentation.scss',
-    },
+    }, options.entry || {}),  // Merge with env dependent settings
+    output: Object.assign({
+      path: helpers.root('public/js'),
+      publicPath: '/js/',
+      filename: '[name]-[hash].js',
+      chunkFilename: '[id]-[chunkhash].js',
+    }, options.output || {}), // Merge with env dependent settings
     externals: {
     externals: {
       // require("jquery") is external and available
       // require("jquery") is external and available
       //  on the global var jQuery
       //  on the global var jQuery
@@ -53,7 +60,7 @@ module.exports = function(options) {
       }
       }
     },
     },
     module: {
     module: {
-      rules: [
+      rules: options.module.rules.concat([
         {
         {
           test: /.jsx?$/,
           test: /.jsx?$/,
           exclude: {
           exclude: {
@@ -64,10 +71,7 @@ module.exports = function(options) {
             ]
             ]
           },
           },
           use: [{
           use: [{
-            loader: 'babel-loader?cacheDirectory',
-            options: {
-              plugins: ['lodash'],
-            }
+            loader: 'babel-loader?cacheDirectory'
           }]
           }]
         },
         },
         {
         {
@@ -100,30 +104,30 @@ module.exports = function(options) {
           test: /\.(eot|woff2?|svg|ttf)([?]?.*)$/,
           test: /\.(eot|woff2?|svg|ttf)([?]?.*)$/,
           use: 'file-loader',
           use: 'file-loader',
         }
         }
-      ]
+      ])
     },
     },
-    plugins: [
+    plugins: options.plugins.concat([
 
 
-      new AssetsPlugin({
-        path: helpers.root('public/js'),
-        filename: 'webpack-assets.json',
-        prettyPrint: true,
-      }),
+      new WebpackAssetsManifest({ publicPath: true }),
 
 
-      new CommonsChunkPlugin({
-        name: 'commons',
-        chunks: ['app', 'legacy', 'legacy-form', 'legacy-admin'],
-        minChunks: module => /node_modules/.test(module.resource),
-      }),
-      new CommonsChunkPlugin({
-        name: 'commons',
-        chunks: ['commons', 'legacy-presentation'],
-      }),
-      new CommonsChunkPlugin({
-        name: 'commons',
-        chunks: ['commons', 'plugin'],
+      new webpack.DefinePlugin({
+        'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
       }),
       }),
 
 
+      // new CommonsChunkPlugin({
+      //   name: 'commons',
+      //   chunks: ['app', 'legacy', 'legacy-form', 'legacy-admin'],
+      //   minChunks: module => /node_modules/.test(module.resource),
+      // }),
+      // new CommonsChunkPlugin({
+      //   name: 'commons',
+      //   chunks: ['commons', 'legacy-presentation'],
+      // }),
+      // new CommonsChunkPlugin({
+      //   name: 'commons',
+      //   chunks: ['commons', 'plugin'],
+      // }),
+
       // ignore
       // ignore
       new webpack.IgnorePlugin(/^\.\/lib\/deflate\.js/, /markdown-it-plantuml/),
       new webpack.IgnorePlugin(/^\.\/lib\/deflate\.js/, /markdown-it-plantuml/),
 
 
@@ -132,6 +136,12 @@ module.exports = function(options) {
         $: 'jquery',
         $: 'jquery',
       }),
       }),
 
 
-    ]
+    ]),
+
+    devtool: options.devtool,
+    target: 'web', // Make web variables accessible to webpack, e.g. window
+    performance: options.performance || {},
+    optimization: options.optimization || {},
+    stats: options.stats || {},
   };
   };
 };
 };

+ 42 - 80
config/webpack.dev.js

@@ -5,98 +5,60 @@
 const path = require('path');
 const path = require('path');
 const webpack = require('webpack');
 const webpack = require('webpack');
 const helpers = require('./helpers');
 const helpers = require('./helpers');
-const webpackMerge = require('webpack-merge');
-const webpackMergeDll = webpackMerge.strategy({plugins: 'replace'});
-const commonConfig = require('./webpack.common.js');
 
 
 /*
 /*
  * Webpack Plugins
  * Webpack Plugins
  */
  */
-const DllBundlesPlugin = require('webpack-dll-bundles-plugin').DllBundlesPlugin;
-const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 
 
-/*
- * Webpack Constants
- */
-const ANALYZE = process.env.ANALYZE;
-const ENV = process.env.ENV = process.env.NODE_ENV = 'development';
 
 
 /*
 /*
  * Webpack configuration
  * Webpack configuration
  *
  *
  * See: http://webpack.github.io/docs/configuration.html#cli
  * See: http://webpack.github.io/docs/configuration.html#cli
  */
  */
-module.exports = function(options) {
-  return webpackMerge(commonConfig({ env: ENV }), {
-    devtool: 'cheap-module-eval-source-map',
-    entry: {
-      dev: './resource/js/dev',
-    },
-    output: {
-      path: helpers.root('public/js'),
-      publicPath: '/js/',
-      filename: '[name].bundle.js',
-    },
-    resolve: {
-      extensions: ['.js', '.json'],
-      modules: [helpers.root('src'), helpers.root('node_modules'), path.join(process.env.HOME, '.node_modules')],
-    },
-    module: {
-      rules: [
-        {
-          test: /\.css$/,
-          use: [
-            'style-loader',
-            { loader: 'css-loader', options: { sourceMap: true } },
-          ],
-          include: [helpers.root('resource/styles/scss')]
-        },
-        {
-          test: /\.scss$/,
-          use: [
-            'style-loader',
-            { loader: 'css-loader', options: { sourceMap: true } },
-            { loader: 'sass-loader', options: { sourceMap: true } },
-          ],
-          include: [helpers.root('resource/styles/scss')]
-        },
-      ],
-    },
-    plugins: [
+module.exports = require('./webpack.common')({
+  mode: 'development',
+  devtool: 'cheap-module-eval-source-map',
+  entry: {
+    dev: './resource/js/dev',
+  },
+  resolve: {
+    // TODO merge in webpack.common.js
+    modules: [path.join(process.env.HOME, '.node_modules')],
+  },
+  module: {
+    rules: [
+      {
+        test: /\.css$/,
+        use: [
+          'style-loader',
+          { loader: 'css-loader', options: { sourceMap: true } },
+        ],
+        include: [helpers.root('resource/styles/scss')]
+      },
+      {
+        test: /\.scss$/,
+        use: [
+          'style-loader',
+          { loader: 'css-loader', options: { sourceMap: true } },
+          { loader: 'sass-loader', options: { sourceMap: true } },
+        ],
+        include: [helpers.root('resource/styles/scss')]
+      },
+    ],
+  },
+  plugins: [
 
 
-      new DllBundlesPlugin({
-        bundles: {
-          vendor: [
-            'axios',
-            'codemirror',
-            'date-fns',
-            'diff',
-            'diff2html',
-            'jquery-ui',
-            'markdown-it',
-            'metismenu',
-            'react',
-            'react-dom',
-            'react-bootstrap',
-            'react-bootstrap-typeahead',
-            'react-dropzone',
-            'socket.io-client',
-            'toastr',
-          ],
-        },
-        dllDir: helpers.root('public/dll'),
-        webpackConfig: webpackMergeDll(commonConfig({env: ENV}), {
-          devtool: undefined,
-          plugins: [],
-        })
-      }),
+    new webpack.DllReferencePlugin({
+      context: helpers.root('public/dll'),
+      manifest: path.join(helpers.root('public/dll'), 'manifest.json')
+    }),
 
 
-      new webpack.NoEmitOnErrorsPlugin(),
+    new webpack.HotModuleReplacementPlugin(),
 
 
-      new BundleAnalyzerPlugin({
-        analyzerMode: ANALYZE ? 'server' : 'disabled',
-      }),
+  ],
+  performance: {
+    hints: false
+  }
 
 
-    ]
-  });
-};
+});

+ 28 - 0
config/webpack.dll.js

@@ -0,0 +1,28 @@
+/**
+ * @author: Yuki Takei <yuki@weseek.co.jp>
+ */
+const path = require('path');
+const webpack = require('webpack');
+const helpers = require('./helpers');
+
+
+module.exports = {
+  mode: 'development',
+  entry: {
+    dlls: ['react', 'react-dom']
+  },
+  output: {
+    path: helpers.root('public/dll'),
+    filename: 'dll.js'
+  },
+  resolve: {
+    extensions: ['.js', '.json'],
+    modules: [helpers.root('src'), helpers.root('node_modules')],
+  },
+  plugins: [
+    new webpack.DllPlugin({
+      path: path.join(helpers.root('public/dll'), 'manifest.json'),
+      name: '[name]_[hash]'
+    })
+  ]
+};

+ 63 - 96
config/webpack.prod.js

@@ -3,117 +3,84 @@
  */
  */
 
 
 const helpers = require('./helpers');
 const helpers = require('./helpers');
-const webpack = require('webpack');
-const webpackMerge = require('webpack-merge'); // used to merge webpack configs
-const commonConfig = require('./webpack.common.js'); // the settings that are common to prod and dev
 
 
 /**
 /**
  * Webpack Plugins
  * Webpack Plugins
  */
  */
-const ExtractTextPlugin = require('extract-text-webpack-plugin');
-const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');
-const OptimizeJsPlugin = require('optimize-js-plugin');
+const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 
 
 /**
 /**
  * Webpack Constants
  * Webpack Constants
  */
  */
 const ANALYZE = process.env.ANALYZE;
 const ANALYZE = process.env.ANALYZE;
-const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
 
 
-module.exports = function(env) {
-  return webpackMerge(commonConfig({ env: ENV }), {
-    devtool: undefined,
-    output: {
-      path: helpers.root('public/js'),
-      publicPath: '/js/',
-      filename: '[name].[chunkhash].bundle.js',
-      sourceMapFilename: '[name].[chunkhash].bundle.map',
-      chunkFilename: '[id].[chunkhash].chunk.js'
-    },
-    module: {
-      rules: [
-        {
-          test: /\.scss$/,
-          use: ExtractTextPlugin.extract({
-            fallback: 'style-loader',
-            use: [
-              { loader: 'css-loader', options: {
-                sourceMap: false,
-                minimize: true
-              } },
-              { loader: 'postcss-loader', options: {
-                sourceMap: false,
-                plugins: (loader) => [
-                  require('autoprefixer')()
-                ]
-              } },
-              { loader: 'sass-loader', options: { sourceMap: false } }
+module.exports = require('./webpack.common')({
+  mode: 'production',
+  devtool: undefined,
+  output: {
+    filename: '[name].[chunkhash].bundle.js',
+    chunkFilename: '[name].[id].[chunkhash].chunk.js'
+  },
+  module: {
+    rules: [
+      {
+        test: /\.scss$/,
+        use: [
+          MiniCssExtractPlugin.loader,
+          'css-loader',
+          { loader: 'postcss-loader', options: {
+            sourceMap: false,
+            plugins: (loader) => [
+              require('autoprefixer')()
             ]
             ]
-          }),
-          include: [helpers.root('resource/styles/scss')]
-        }
-      ]
-    },
-    plugins: [
+          } },
+          'sass-loader'
+        ],
+        include: [helpers.root('resource/styles/scss')]
+      }
+    ]
+  },
+  plugins: [
 
 
-      new webpack.DefinePlugin({
-        'process.env': {
-          NODE_ENV: JSON.stringify(ENV),
-        }
-      }),
+    new MiniCssExtractPlugin({
+      filename: '[name].[hash].css',
+      chunkFilename: '[id].[hash].css'
+    }),
 
 
-      new ExtractTextPlugin('[name].[contenthash].css'),
-
-      new OptimizeJsPlugin({
-        sourceMap: false
-      }),
+    new BundleAnalyzerPlugin({
+      analyzerMode: ANALYZE ? 'static' : 'disabled',
+      reportFilename: helpers.root('report/bundle-analyzer.html'),
+      openAnalyzer: false,
+    }),
 
 
+  ],
+  optimization: {
+    namedModules: true,
+    minimizer: [
       new UglifyJsPlugin({
       new UglifyJsPlugin({
-        // beautify: true, //debug
-        // mangle: false, //debug
-        // dead_code: false, //debug
-        // unused: false, //debug
-        // deadCode: false, //debug
-        // compress: {
-        //   screw_ie8: true,
-        //   keep_fnames: true,
-        //   drop_debugger: false,
-        //   dead_code: false,
-        //   unused: false
-        // }, // debug
-        // comments: true, //debug
-
-
-        beautify: false, //prod
-        output: {
-          comments: false
-        }, //prod
-        mangle: {
-          screw_ie8: true
-        }, //prod
-        compress: {
-          screw_ie8: true,
-          warnings: false,
-          conditionals: true,
-          unused: true,
-          comparisons: true,
-          sequences: true,
-          dead_code: true,
-          evaluate: true,
-          if_return: true,
-          join_vars: true,
-          negate_iife: false // we need this for lazy v8
-        },
-      }),
-
-      new BundleAnalyzerPlugin({
-        analyzerMode: ANALYZE ? 'static' : 'disabled',
-        reportFilename: helpers.root('report/bundle-analyzer.html'),
-        openAnalyzer: false,
+        cache: true,
+        parallel: true,
       }),
       }),
-
+      new OptimizeCSSAssetsPlugin({})
     ],
     ],
-
-  });
-};
+    splitChunks: {
+      cacheGroups: {
+        commons: {
+          chunks: 'initial',
+          minChunks: 2,
+          minSize: 1,
+        },
+        vendor: {
+          test: /node_modules/,
+          chunks: 'initial',
+          name: 'vendor',
+          priority: 10,
+          enforce: true
+        }
+      }
+    }
+  },
+});

+ 1 - 1
lib/crowi/express-init.js

@@ -89,7 +89,7 @@ module.exports = function(crowi, app) {
   app.use(express.static(crowi.publicDir, staticOption));
   app.use(express.static(crowi.publicDir, staticOption));
   app.engine('html', swig.renderFile);
   app.engine('html', swig.renderFile);
   app.use(webpackAssets(
   app.use(webpackAssets(
-    path.join(crowi.publicDir, 'js/webpack-assets.json'),
+    path.join(crowi.publicDir, 'js/manifest.json'),
     { devMode: (crowi.node_env === 'development') })
     { devMode: (crowi.node_env === 'development') })
   );
   );
   // app.set('view cache', false);  // Default: true in production, otherwise undefined. -- 2017.07.04 Yuki Takei
   // app.set('view cache', false);  // Default: true in production, otherwise undefined. -- 2017.07.04 Yuki Takei

+ 1 - 1
lib/views/_form.html

@@ -1,5 +1,5 @@
 {% block html_head_loading_legacy %}
 {% block html_head_loading_legacy %}
-  <script src="{{ webpack_asset('legacy-form').js }}" defer></script>
+  <script src="{{ webpack_asset('legacy-form.js') }}" defer></script>
   {% parent %}
   {% parent %}
 {% endblock %}
 {% endblock %}
 
 

+ 4 - 4
lib/views/admin/customize.html

@@ -4,11 +4,11 @@
 
 
 {% block style_css_block %}
 {% block style_css_block %}
   {% if env === 'development' %}
   {% if env === 'development' %}
-    <script src="{{ webpack_asset('style').js }}"></script>
-    <script src="{{ webpack_asset('style-theme-' + theme()).js }}"></script>
+    <script src="{{ webpack_asset('style.js') }}"></script>
+    <script src="{{ webpack_asset('style-theme-' + theme() + '.js') }}"></script>
   {% else %}
   {% else %}
-    <link rel="stylesheet" href="{{ webpack_asset('style').css }}">
-    <link rel="stylesheet" id="jssDefault" {# append id for theme selector #} href="{{ webpack_asset('style-theme-' + theme()).css }}">
+    <link rel="stylesheet" href="{{ webpack_asset('style.css') }}">
+    <link rel="stylesheet" id="jssDefault" {# append id for theme selector #} href="{{ webpack_asset('style-theme-' + theme() + '.css') }}">
   {% endif %}
   {% endif %}
 {% endblock %}
 {% endblock %}
 
 

+ 1 - 1
lib/views/admin/widget/theme-colorbox.html

@@ -1,7 +1,7 @@
 <a id="theme-option-{{name}}" href="#"
 <a id="theme-option-{{name}}" href="#"
     class="{{name}} {% if name === settingForm['customize:theme'] %}active{% endif %}"
     class="{{name}} {% if name === settingForm['customize:theme'] %}active{% endif %}"
     onclick="selectTheme('{{name}}')"
     onclick="selectTheme('{{name}}')"
-    data-theme="{{ webpack_asset('style-theme-' + name).css }}">
+    data-theme="{{ webpack_asset('style-theme-' + name + '.css') }}">
 
 
   <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
   <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
     <title>{{name}}</title>
     <title>{{name}}</title>

+ 1 - 1
lib/views/layout/admin.html

@@ -6,7 +6,7 @@
 
 
 {% block html_additional_headers %}
 {% block html_additional_headers %}
   {% parent %}
   {% parent %}
-  <script src="{{ webpack_asset('legacy-admin').js }}" defer></script>
+  <script src="{{ webpack_asset('legacy-admin.js') }}" defer></script>
 {% endblock %}
 {% endblock %}
 
 
 {# disable custom script in admin page #}
 {# disable custom script in admin page #}

+ 9 - 9
lib/views/layout/layout.html

@@ -64,32 +64,32 @@ gh/highlightjs/cdn-release@9.12.0/build/languages/yaml.min.js
 
 
   {% if env === 'development' %}
   {% if env === 'development' %}
     <script src="/dll/vendor.dll.js"></script>
     <script src="/dll/vendor.dll.js"></script>
-    <script src="{{ webpack_asset('dev').js }}" async></script>
+    <script src="{{ webpack_asset('dev.js') }}" async></script>
     <!-- Browsersync -->
     <!-- Browsersync -->
     <script id="__bs_script__">//<![CDATA[
     <script id="__bs_script__">//<![CDATA[
       document.write("<script async src='http://HOST:3001/browser-sync/browser-sync-client.js?v=2.23.6'><\/script>".replace("HOST", location.hostname));
       document.write("<script async src='http://HOST:3001/browser-sync/browser-sync-client.js?v=2.23.6'><\/script>".replace("HOST", location.hostname));
     //]]></script>
     //]]></script>
   {% endif %}
   {% endif %}
 
 
-  <script src="{{ webpack_asset('commons').js }}" defer></script>
+  <script src="{{ webpack_asset('vendor.js') }}" defer></script>
   {% if isEnabledPlugins() %}
   {% if isEnabledPlugins() %}
-  <script src="{{ webpack_asset('plugin').js }}" defer></script>
+  <script src="{{ webpack_asset('plugin.js') }}" defer></script>
   {% endif %}
   {% endif %}
   {% block html_head_loading_legacy %}
   {% block html_head_loading_legacy %}
-  <script src="{{ webpack_asset('legacy').js }}" defer></script>
+  <script src="{{ webpack_asset('legacy.js') }}" defer></script>
   {% endblock %}
   {% endblock %}
   {% block html_head_loading_app %}
   {% block html_head_loading_app %}
-  <script src="{{ webpack_asset('app').js }}" defer></script>
+  <script src="{{ webpack_asset('app.js') }}" defer></script>
   {% endblock %}
   {% endblock %}
 
 
   <!-- styles -->
   <!-- styles -->
   {% block style_css_block %}
   {% block style_css_block %}
     {% if env === 'development' %}
     {% if env === 'development' %}
-      <script src="{{ webpack_asset('style').js }}"></script>
-      <script src="{{ webpack_asset('style-theme-' + theme()).js }}"></script>
+      <script src="{{ webpack_asset('style.js') }}"></script>
+      <script src="{{ webpack_asset('style-theme-' + theme() + '.js') }}"></script>
     {% else %}
     {% else %}
-      <link rel="stylesheet" href="{{ webpack_asset('style').css }}">
-      <link rel="stylesheet" href="{{ webpack_asset('style-theme-' + theme()).css }}">
+      <link rel="stylesheet" href="{{ webpack_asset('style.css') }}">
+      <link rel="stylesheet" href="{{ webpack_asset('style-theme-' + theme() + '.css') }}">
     {% endif %}
     {% endif %}
   {% endblock %}
   {% endblock %}
 
 

+ 13 - 6
package.json

@@ -21,8 +21,11 @@
   },
   },
   "scripts": {
   "scripts": {
     "build:dev:analyze": "cross-env ANALYZE=1 npm run build:dev",
     "build:dev:analyze": "cross-env ANALYZE=1 npm run build:dev",
-    "build:dev:watch": "npm run build:dev -- --watch",
-    "build:dev": "npm run clean:js && webpack --config config/webpack.dev.js --progress --profile",
+    "build:dev:app:watch": "npm run build:dev:app -- --watch",
+    "build:dev:app": "npm run clean:js && webpack --config config/webpack.dev.js --progress --profile",
+    "build:dev:watch": "npm-run-all -p build:dll build:dev:app:watch",
+    "build:dev": "npm-run-all -p build:dll build:dev:app",
+    "build:dll": "webpack --config config/webpack.dll.js",
     "build:prod:analyze": "cross-env ANALYZE=1 npm run build:prod",
     "build:prod:analyze": "cross-env ANALYZE=1 npm run build:prod",
     "build:prod": "npm run clean && webpack --config config/webpack.prod.js --progress --profile --bail",
     "build:prod": "npm run clean && webpack --config config/webpack.prod.js --progress --profile --bail",
     "build": "npm run build:dev:watch",
     "build": "npm run build:dev:watch",
@@ -111,7 +114,6 @@
   },
   },
   "devDependencies": {
   "devDependencies": {
     "@alienfast/i18next-loader": "^1.0.16",
     "@alienfast/i18next-loader": "^1.0.16",
-    "assets-webpack-plugin": "^3.6.0",
     "autoprefixer": "^8.2.0",
     "autoprefixer": "^8.2.0",
     "babel-core": "^6.25.0",
     "babel-core": "^6.25.0",
     "babel-loader": "^7.1.1",
     "babel-loader": "^7.1.1",
@@ -154,13 +156,14 @@
     "markdown-it-toc-and-anchor-with-slugid": "^1.1.4",
     "markdown-it-toc-and-anchor-with-slugid": "^1.1.4",
     "markdown-table": "^1.1.1",
     "markdown-table": "^1.1.1",
     "metismenu": "^2.7.4",
     "metismenu": "^2.7.4",
+    "mini-css-extract-plugin": "^0.4.0",
     "mocha": "^5.0.0",
     "mocha": "^5.0.0",
     "morgan": "^1.9.0",
     "morgan": "^1.9.0",
     "node-dev": "^3.1.3",
     "node-dev": "^3.1.3",
     "node-sass": "^4.5.0",
     "node-sass": "^4.5.0",
     "normalize-path": "^3.0.0",
     "normalize-path": "^3.0.0",
     "on-headers": "^1.0.1",
     "on-headers": "^1.0.1",
-    "optimize-js-plugin": "0.0.4",
+    "optimize-css-assets-webpack-plugin": "^4.0.2",
     "plantuml-encoder": "^1.2.5",
     "plantuml-encoder": "^1.2.5",
     "postcss-loader": "^2.1.3",
     "postcss-loader": "^2.1.3",
     "react-bootstrap": "^0.32.1",
     "react-bootstrap": "^0.32.1",
@@ -177,10 +180,14 @@
     "style-loader": "^0.21.0",
     "style-loader": "^0.21.0",
     "throttle-debounce": "^2.0.0",
     "throttle-debounce": "^2.0.0",
     "toastr": "^2.1.2",
     "toastr": "^2.1.2",
+    "uglifyjs-webpack-plugin": "^1.2.5",
     "url-join": "^4.0.0",
     "url-join": "^4.0.0",
-    "webpack": "3.11.0",
+    "webpack": "^4.12.0",
+    "webpack-assets-manifest": "^3.0.1",
     "webpack-bundle-analyzer": "^2.9.0",
     "webpack-bundle-analyzer": "^2.9.0",
-    "webpack-dll-bundles-plugin": "^1.0.0-beta.5",
+    "webpack-cli": "^3.0.8",
+    "webpack-dev-middleware": "^3.1.3",
+    "webpack-hot-middleware": "^2.22.2",
     "webpack-merge": "~4.1.0"
     "webpack-merge": "~4.1.0"
   },
   },
   "_moduleAliases": {
   "_moduleAliases": {

File diff ditekan karena terlalu besar
+ 495 - 94
yarn.lock


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini