webpack.config.js 11.0 KB
Newer Older
1 2
'use strict';

P
Phil Hughes 已提交
3
var fs = require('fs');
4 5
var path = require('path');
var webpack = require('webpack');
6
var StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin;
7
var CopyWebpackPlugin = require('copy-webpack-plugin');
M
Mike Greiling 已提交
8
var CompressionPlugin = require('compression-webpack-plugin');
9
var NameAllModulesPlugin = require('name-all-modules-plugin');
10
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
11
var WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
12

13
var ROOT_PATH = path.resolve(__dirname, '..');
14
var IS_PRODUCTION = process.env.NODE_ENV === 'production';
15
var IS_DEV_SERVER = process.argv.join(' ').indexOf('webpack-dev-server') !== -1;
16
var DEV_SERVER_HOST = process.env.DEV_SERVER_HOST || 'localhost';
17
var DEV_SERVER_PORT = parseInt(process.env.DEV_SERVER_PORT, 10) || 3808;
18
var DEV_SERVER_LIVERELOAD = process.env.DEV_SERVER_LIVERELOAD !== 'false';
19
var WEBPACK_REPORT = process.env.WEBPACK_REPORT;
M
Mike Greiling 已提交
20
var NO_COMPRESSION = process.env.NO_COMPRESSION;
21 22

var config = {
23 24 25 26
  // because sqljs requires fs.
  node: {
    fs: "empty"
  },
27
  context: path.join(ROOT_PATH, 'app/assets/javascripts'),
28
  entry: {
29
    account:              './profile/account/index.js',
30
    balsamiq_viewer:      './blob/balsamiq_viewer.js',
31 32
    blob:                 './blob_edit/blob_bundle.js',
    boards:               './boards/boards_bundle.js',
33
    common:               './commons/index.js',
34
    common_vue:           './vue_shared/vue_resource_interceptor.js',
35
    cycle_analytics:      './cycle_analytics/cycle_analytics_bundle.js',
F
Filipa Lacerda 已提交
36
    commit_pipelines:     './commit/pipelines/pipelines_bundle.js',
37
    deploy_keys:          './deploy_keys/index.js',
38 39
    diff_notes:           './diff_notes/diff_notes_bundle.js',
    environments:         './environments/environments_bundle.js',
F
Filipa Lacerda 已提交
40
    environments_folder:  './environments/folder/environments_folder_bundle.js',
41
    filtered_search:      './filtered_search/filtered_search_bundle.js',
42
    graphs:               './graphs/graphs_bundle.js',
43 44
    graphs_charts:        './graphs/graphs_charts.js',
    graphs_show:          './graphs/graphs_show.js',
45
    group:                './group.js',
A
Alfredo Sumaran 已提交
46
    groups:               './groups/index.js',
F
Filipa Lacerda 已提交
47
    groups_list:          './groups_list.js',
48
    help:                 './help/help.js',
T
Tim Zallmann 已提交
49
    how_to_merge:         './how_to_merge.js',
50
    issue_show:           './issue_show/index.js',
K
kushalpandya 已提交
51
    integrations:         './integrations',
52
    job_details:          './jobs/job_details_bundle.js',
P
Phil Hughes 已提交
53
    locale:               './locale/index.js',
54
    main:                 './main.js',
55
    merge_conflicts:      './merge_conflicts/merge_conflicts_bundle.js',
56
    monitoring:           './monitoring/monitoring_bundle.js',
57
    network:              './network/network_bundle.js',
P
Phil Hughes 已提交
58
    notebook_viewer:      './blob/notebook_viewer.js',
59
    notes:                './notes/index.js',
S
Sam Rose 已提交
60
    pdf_viewer:           './blob/pdf_viewer.js',
61
    pipelines:            './pipelines/pipelines_bundle.js',
T
Tim Zallmann 已提交
62
    pipelines_charts:     './pipelines/pipelines_charts.js',
63 64
    pipelines_details:    './pipelines/pipeline_details_bundle.js',
    pipelines_times:      './pipelines/pipelines_times.js',
65
    profile:              './profile/profile_bundle.js',
66
    project_import_gl:    './projects/project_import_gitlab_project.js',
67
    project_new:          './projects/project_new.js',
K
kushalpandya 已提交
68
    prometheus_metrics:   './prometheus_metrics',
69
    protected_branches:   './protected_branches',
70
    protected_tags:       './protected_tags',
71
    registry_list:        './registry/index.js',
M
Mike Greiling 已提交
72
    repo:                 './repo/index.js',
73
    sidebar:              './sidebar/sidebar_bundle.js',
74 75
    schedule_form:        './pipeline_schedules/pipeline_schedule_form_bundle.js',
    schedules_index:      './pipeline_schedules/pipeline_schedules_index_bundle.js',
76
    snippet:              './snippet/snippet_bundle.js',
77
    sketch_viewer:        './blob/sketch_viewer.js',
P
Phil Hughes 已提交
78
    stl_viewer:           './blob/stl_viewer.js',
79
    terminal:             './terminal/terminal_bundle.js',
M
Mike Greiling 已提交
80
    u2f:                  ['vendor/u2f'],
81
    ui_development_kit:   './ui_development_kit.js',
82
    raven:                './raven/index.js',
F
Fatih Acet 已提交
83
    vue_merge_request_widget: './vue_merge_request_widget/index.js',
84
    test:                 './test.js',
85
    two_factor_auth:      './two_factor_auth.js',
86
    users:                './users/index.js',
87
    performance_bar:      './performance_bar.js',
88
    webpack_runtime:      './webpack.js',
89 90 91 92 93
  },

  output: {
    path: path.join(ROOT_PATH, 'public/assets/webpack'),
    publicPath: '/assets/webpack/',
94 95
    filename: IS_PRODUCTION ? '[name].[chunkhash].bundle.js' : '[name].bundle.js',
    chunkFilename: IS_PRODUCTION ? '[name].[chunkhash].chunk.js' : '[name].chunk.js',
96 97
  },

M
Mike Greiling 已提交
98
  module: {
M
Mike Greiling 已提交
99
    rules: [
M
Mike Greiling 已提交
100
      {
101
        test: /\.js$/,
102
        exclude: /(node_modules|vendor\/assets)/,
M
Mike Greiling 已提交
103
        loader: 'babel-loader',
F
Filipa Lacerda 已提交
104
      },
105 106
      {
        test: /\.vue$/,
M
Mike Greiling 已提交
107
        loader: 'vue-loader',
108
      },
F
Filipa Lacerda 已提交
109 110
      {
        test: /\.svg$/,
M
Mike Greiling 已提交
111 112
        loader: 'raw-loader',
      },
S
Sam Rose 已提交
113
      {
114
        test: /\.(gif|png)$/,
S
Sam Rose 已提交
115
        loader: 'url-loader',
116
        options: { limit: 2048 },
S
Sam Rose 已提交
117
      },
P
Phil Hughes 已提交
118 119 120 121
      {
        test: /\_worker\.js$/,
        loader: 'worker-loader',
      },
M
Mike Greiling 已提交
122
      {
123
        test: /\.(worker(\.min)?\.js|pdf|bmpr)$/,
S
Sam Rose 已提交
124 125
        exclude: /node_modules/,
        loader: 'file-loader',
126 127 128
        options: {
          name: '[name].[hash].[ext]',
        }
S
Sam Rose 已提交
129
      },
130 131 132 133 134 135 136 137 138 139
      {
        test: /monaco-editor\/\w+\/vs\/loader\.js$/,
        use: [
          { loader: 'exports-loader', options: 'l.global' },
          { loader: 'imports-loader', options: 'l=>{},this=>l,AMDLoader=>this,module=>undefined' },
        ],
      }
    ],

    noParse: [/monaco-editor\/\w+\/vs\//],
M
Mike Greiling 已提交
140 141
  },

142 143 144
  plugins: [
    // manifest filename must match config.webpack.manifest_filename
    // webpack-rails only needs assetsByChunkName to function properly
145 146 147 148 149 150 151 152 153 154 155 156
    new StatsWriterPlugin({
      filename: 'manifest.json',
      transform: function(data, opts) {
        var stats = opts.compiler.getStats().toJson({
          chunkModules: false,
          source: false,
          chunks: false,
          modules: false,
          assets: true
        });
        return JSON.stringify(stats, null, 2);
      }
P
Phil Hughes 已提交
157
    }),
M
Mike Greiling 已提交
158 159

    // prevent pikaday from including moment.js
P
Phil Hughes 已提交
160
    new webpack.IgnorePlugin(/moment/, /pikaday/),
M
Mike Greiling 已提交
161

162 163 164 165 166 167
    // fix legacy jQuery plugins which depend on globals
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
    }),

168
    // assign deterministic module ids
169
    new webpack.NamedModulesPlugin(),
170
    new NameAllModulesPlugin(),
171

172 173 174 175 176
    // assign deterministic chunk ids
    new webpack.NamedChunksPlugin((chunk) => {
      if (chunk.name) {
        return chunk.name;
      }
177
      return chunk.mapModules((m) => {
178 179 180 181 182
        var chunkPath = m.request.split('!').pop();
        return path.relative(m.context, chunkPath);
      }).join('_');
    }),

183 184 185 186 187 188 189
    // create cacheable common library bundle for all vue chunks
    new webpack.optimize.CommonsChunkPlugin({
      name: 'common_vue',
      chunks: [
        'boards',
        'commit_pipelines',
        'cycle_analytics',
P
Phil Hughes 已提交
190
        'deploy_keys',
191 192 193
        'diff_notes',
        'environments',
        'environments_folder',
194
        'filtered_search',
A
Alfredo Sumaran 已提交
195
        'groups',
196
        'issue_show',
197
        'job_details',
198
        'merge_conflicts',
199
        'monitoring',
P
Phil Hughes 已提交
200
        'notebook_viewer',
201
        'notes',
S
Sam Rose 已提交
202
        'pdf_viewer',
203
        'pipelines',
204
        'pipelines_details',
205
        'registry_list',
M
Mike Greiling 已提交
206
        'repo',
207 208 209
        'schedule_form',
        'schedules_index',
        'sidebar',
210
        'vue_merge_request_widget',
211
      ],
212 213 214
      minChunks: function(module, count) {
        return module.resource && (/vue_shared/).test(module.resource);
      },
215 216
    }),

217 218 219
    // create cacheable common library bundle for all d3 chunks
    new webpack.optimize.CommonsChunkPlugin({
      name: 'common_d3',
220 221
      chunks: [
        'graphs',
222
        'graphs_show',
223
        'monitoring',
224
        'users',
225
      ],
226 227 228
      minChunks: function (module, count) {
        return module.resource && /d3-/.test(module.resource);
      },
229 230
    }),

231
    // create cacheable common library bundles
232
    new webpack.optimize.CommonsChunkPlugin({
233
      names: ['main', 'common', 'webpack_runtime'],
234
    }),
235

M
Mike Greiling 已提交
236 237 238
    // enable scope hoisting
    new webpack.optimize.ModuleConcatenationPlugin(),

239
    // copy pre-compiled vendor libraries verbatim
240 241
    new CopyWebpackPlugin([
      {
242 243 244
        from: path.join(ROOT_PATH, `node_modules/monaco-editor/${IS_PRODUCTION ? 'min' : 'dev'}/vs`),
        to: 'monaco-editor/vs',
        transform: function(content, path) {
245
          if (/\.js$/.test(path) && !/worker/i.test(path) && !/typescript/i.test(path)) {
246 247 248
            return (
              '(function(){\n' +
              'var define = this.define, require = this.require;\n' +
249
              'window.define = define; window.require = require;\n' +
250 251 252 253 254 255
              content +
              '\n}.call(window.__monaco_context__ || (window.__monaco_context__ = {})));'
            );
          }
          return content;
        }
256 257
      }
    ]),
M
Mike Greiling 已提交
258 259 260
  ],

  resolve: {
261
    extensions: ['.js'],
262
    alias: {
263
      '~':              path.join(ROOT_PATH, 'app/assets/javascripts'),
264
      'emojis':         path.join(ROOT_PATH, 'fixtures/emojis'),
265
      'empty_states':   path.join(ROOT_PATH, 'app/views/shared/empty_states'),
266
      'icons':          path.join(ROOT_PATH, 'app/views/shared/icons'),
267
      'images':         path.join(ROOT_PATH, 'app/assets/images'),
268
      'vendor':         path.join(ROOT_PATH, 'vendor/assets/javascripts'),
269
      'vue$':           'vue/dist/vue.esm.js',
270
    }
M
Mike Greiling 已提交
271
  }
272 273
}

274
if (IS_PRODUCTION) {
M
Mike Greiling 已提交
275
  config.devtool = 'source-map';
276
  config.plugins.push(
277
    new webpack.NoEmitOnErrorsPlugin(),
M
Mike Greiling 已提交
278 279 280 281
    new webpack.LoaderOptionsPlugin({
      minimize: true,
      debug: false
    }),
282
    new webpack.optimize.UglifyJsPlugin({
M
Mike Greiling 已提交
283
      sourceMap: true
284 285 286
    }),
    new webpack.DefinePlugin({
      'process.env': { NODE_ENV: JSON.stringify('production') }
M
Mike Greiling 已提交
287
    })
288
  );
M
Mike Greiling 已提交
289

290
  // compression can require a lot of compute time and is disabled in CI
M
Mike Greiling 已提交
291
  if (!NO_COMPRESSION) {
292
    config.plugins.push(new CompressionPlugin());
M
Mike Greiling 已提交
293
  }
294 295 296
}

if (IS_DEV_SERVER) {
297
  config.devtool = 'cheap-module-eval-source-map';
298
  config.devServer = {
299
    host: DEV_SERVER_HOST,
300
    port: DEV_SERVER_PORT,
301
    disableHostCheck: true,
302 303
    headers: { 'Access-Control-Allow-Origin': '*' },
    stats: 'errors-only',
S
Simon Knox 已提交
304
    hot: DEV_SERVER_LIVERELOAD,
305
    inline: DEV_SERVER_LIVERELOAD
306
  };
307 308 309 310
  config.plugins.push(
    // watch node_modules for changes if we encounter a missing module compile error
    new WatchMissingNodeModulesPlugin(path.join(ROOT_PATH, 'node_modules'))
  );
S
Simon Knox 已提交
311 312 313
  if (DEV_SERVER_LIVERELOAD) {
    config.plugins.push(new webpack.HotModuleReplacementPlugin());
  }
314 315
}

316 317 318 319 320 321 322 323 324 325 326 327
if (WEBPACK_REPORT) {
  config.plugins.push(
    new BundleAnalyzerPlugin({
      analyzerMode: 'static',
      generateStatsFile: true,
      openAnalyzer: false,
      reportFilename: path.join(ROOT_PATH, 'webpack-report/index.html'),
      statsFilename: path.join(ROOT_PATH, 'webpack-report/stats.json'),
    })
  );
}

328
module.exports = config;