Commit ddf39f29 authored by Eric Eastwood's avatar Eric Eastwood 🌴

Upgrade from webpack v1 to v4

Fix #2078
parent 83ebd596
......@@ -101,3 +101,4 @@ unread-notification.out.html
node_modules_2
config/overrides
.env
webpack-report/
......@@ -20,7 +20,6 @@ stages:
- /npm_cache/
- npm_cache/
validate:
<<: *node_job
stage: build_unit_test
......@@ -32,7 +31,6 @@ validate:
# to re-use the scripts that GitLab has, https://gitlab.com/gitlab-org/gitlab-ce/issues/57010
- npm run prettier -- --check "**/*.js"
test:
<<: *node_job
variables:
......@@ -67,7 +65,7 @@ mobile-asset-build:
<<: *node_job
stage: build_unit_test
only:
- master
- master
script:
- npm run build-android-assets
- npm run build-ios-assets
......@@ -76,8 +74,6 @@ mobile-asset-build:
- output/android/www
- output/ios/www
.distribute_job: &distribute_job
image: registry.gitlab.com/gitlab-org/gitter/webapp/deploy-build-image:latest
stage: pre_deploy
......@@ -89,14 +85,12 @@ mobile-asset-build:
distribute_beta:
<<: *distribute_job
only:
- develop
- develop
variables:
DIST_S3_URL: s3://gitter-deployments/gitter-webapp/beta
distribute_beta_staging:
<<: *distribute_job
only:
- /^feature\/.*$/
variables:
DIST_S3_URL: s3://gitter-deployments/gitter-webapp/beta-staging
......@@ -168,13 +162,12 @@ deploy-build-image:
tags:
- internal # This has to be within the Gitter network
deploy_beta: &deploy_beta
<<: *deploy_job
dependencies:
- distribute_beta
only:
- develop
- develop
script:
- cd $ANSIBLE_DIR && ansible-playbook -i beta --vault-password-file "/root/.vault_pass" playbooks/gitter/webapp-deploy.yml
environment:
......@@ -200,6 +193,8 @@ deploy_beta_staging: &deploy_beta_staging
deploy_beta_staging_manual:
<<: *deploy_beta_staging
when: manual
only:
- /.*/
deploy_staging: &deploy_staging
<<: *deploy_job
......@@ -231,7 +226,6 @@ deploy_prod_manual: &deploy_prod
name: prod
url: https://gitter.im
docker-base:
image: docker:latest
stage: docker_images
......
......@@ -28,6 +28,9 @@ upload-to-s3:
ci-test:
mkdir -p output/
# Create the `output/assets/js/webpack-manifest.json` so
# we know which chunks to serve in `boot-script-utils.js`
gulp clientapp:compile:webpack
gulp test --test-coverage --test-suite docker --test-xunit-reports --test-bail
test: clean
......
......@@ -58,3 +58,20 @@ which will just 404 on a separate device when you try to sign in.
Recreate your secrets using your local network IP, see https://gitlab.com/gitlab-org/gitter/webapp#configure-service-secrets
Restart the server. You should now be able to access Gitter over your local IP from other devices
## View `webpack` bundle visualization (webpack report)
Run the webapp with the `WEBPACK_REPORT` environment variable set to generate the HTML report
macOS/Linux:
```
WEBPACK_REPORT=1 npm start
```
Windows:
```
set WEBPACK_REPORT=1&&npm start
```
Open `webpack-report/index.html` in your browser
......@@ -4,7 +4,7 @@ var isGitHubUser = require('../shared/is-github-user');
var avatarCdnResolver = require('../shared/avatar-cdn-resolver');
var extractTwitterAvatarInfo = require('../shared/extract-twitter-avatar-info');
var DEFAULT = require('url?limit=1024!../../../public/images/default-avatar.png'); // eslint-disable-line
var DEFAULT = require('url-loader?limit=1024!../../../public/images/default-avatar.png'); // eslint-disable-line
function getForGitHubUsername(githubUsername) {
return avatarCdnResolver('/gh/u/' + githubUsername);
......
......@@ -2,7 +2,10 @@
var path = require('path');
const IS_PRODUCTION = process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'prod';
var config = {
mode: IS_PRODUCTION ? 'production' : 'development',
entry: {
sw: require.resolve('./service-worker/sw')
},
......
......@@ -25,14 +25,20 @@ exports.bootScript = function(url, parameters) {
var jsRoot = (options && options.jsRoot) || 'js';
var baseUrl = cdnUrlGenerator(jsRoot + '/', options);
var vendorScriptUrl = cdnUrlGenerator(jsRoot + '/vendor.js', options);
var bootScriptUrl = cdnUrlGenerator(jsRoot + '/' + url + '.js', options);
var webpackRuntimeScriptUrl = cdnUrlGenerator(jsRoot + '/runtime.js', options);
var defaultScriptUrl = cdnUrlGenerator(jsRoot + '/default.chunk.js', options);
var vendorScriptUrl = cdnUrlGenerator(jsRoot + '/vendor.chunk.js', options);
var bootScriptUrl = cdnUrlGenerator(jsRoot + '/' + url + '.chunk.js', options);
return util.format(
"<script type='text/javascript'>window.webpackPublicPath = '%s';</script>" +
"<script type='text/javascript' src='%s'></script>" +
"<script type='text/javascript' src='%s'></script>" +
"<script type='text/javascript' src='%s'></script>" +
"<script type='text/javascript' src='%s'></script>",
baseUrl,
webpackRuntimeScriptUrl,
defaultScriptUrl,
vendorScriptUrl,
bootScriptUrl
);
......
This diff is collapsed.
......@@ -167,14 +167,14 @@
"yargs": "^4.2.0"
},
"devDependencies": {
"@babel/core": "^7.2.2",
"@babel/preset-env": "^7.3.1",
"@gitterhq/backbone-proxy-collection": "^2.3.0",
"@gitterhq/cal-heatmap": "^3.6.1",
"@gitterhq/handlebars-loader": "1.2.0-a",
"@gitterhq/styleguide": "^2.0.0",
"@gitterhq/handlebars-loader": "^1.2.0-a",
"@gitterhq/styleguide": "^2.2.0",
"autoprefixer-core": "^6.0.1",
"babel-core": "^6.16.0",
"babel-loader": "^6.4.1",
"babel-preset-es2015": "^6.24.1",
"babel-loader": "^8.0.5",
"backbone-url-resolver": "^0.1.1",
"backbone.cocktail": "^0.5.13",
"backbone.marionette": "^2.4.4",
......@@ -183,7 +183,7 @@
"chokidar": "^2.0.1",
"concurrently": "^2.0.0",
"cross-spawn": "^4.0.2",
"css-loader": "^0.28.11",
"css-loader": "^2.1.0",
"css-mqpacker": "^6.0.1",
"csswring": "^6.0.0",
"cumberbatch-name": "^1.0.9",
......@@ -223,7 +223,6 @@
"gulp-using": "^0.1.1",
"gulp-util": "^3.0.7",
"hammerjs": "^2.0.4",
"istanbul-instrumenter-loader": "^0.1.3",
"jquery": "2.1.0",
"jsmockito": "^1.0.5",
"keymaster": "^1.6.2",
......@@ -241,9 +240,8 @@
"parse-diff": "^0.4.0",
"path-parse": "^1.0.5",
"postcss": "^4.0.0",
"postcss-loader": "^1.3.3",
"postcss-loader": "^3.0.0",
"prettier": "^1.16.1",
"progress-bar-webpack-plugin": "^1.2.0",
"proxyquire": "0.4.0",
"pump": "^1.0.1",
"random-seed": "^0.2.0",
......@@ -254,17 +252,18 @@
"simple-git": "^1.73.0",
"sinon": "1.5.2",
"speedy": "^0.1.1",
"style-loader": "^0.13.1",
"style-loader": "^0.23.1",
"supertest": "^1.2.0",
"supertest-as-promised": "^3.1.0",
"tiny-cookie": "^0.5.5",
"url-loader": "^0.5.7",
"url-loader": "^1.1.2",
"vinyl-file": "^3.0.0",
"webpack": "^1.15.0",
"webpack-dev-middleware": "^1.12.2",
"webpack-stats-plugin": "^0.1.3",
"webpack-stream": "^3.2.0",
"webpack-visualizer-plugin": "^0.1.5"
"webpack": "^4.29.0",
"webpack-bundle-analyzer": "^3.0.3",
"webpack-dev-middleware": "^3.5.1",
"webpack-stats-plugin": "^0.2.1",
"webpack-stream": "^5.2.1",
"webpack-visualizer-plugin": "^0.1.11"
},
"engines": {
"node": ">=6.0.0",
......
'use strict';
require('./utils/webpack');
require('./utils/context');
require('./utils/log');
require('./components/api-client');
// Polyfills
require('core-js/fn/object/assign');
......@@ -3,7 +3,6 @@
var path = require('path');
var _ = require('lodash');
var mainWebpackConfig = require('./webpack.config');
var DedupePlugin = require('webpack/lib/optimize/DedupePlugin');
var mobileConfig = _.extend({}, mainWebpackConfig);
......@@ -15,6 +14,5 @@ mobileConfig.entry = {
};
mobileConfig.plugins = mobileConfig.plugins.slice();
mobileConfig.plugins.push(new DedupePlugin());
module.exports = mobileConfig;
'use strict';
var path = require('path');
var ProvidePlugin = require('webpack/lib/ProvidePlugin');
var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
var ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');
const path = require('path');
const webpack = require('webpack');
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
const ContextReplacementPlugin = require('webpack/lib/ContextReplacementPlugin');
const StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin;
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
var getPostcssStack = require('@gitterhq/styleguide/postcss-stack');
const getPostcssStack = require('@gitterhq/styleguide/postcss-stack');
var devMode = process.env.WEBPACK_DEV_MODE === '1';
// Default to production unless we know for sure we are in dev
const IS_PRODUCTION = process.env.NODE_ENV !== 'development' && process.env.NODE_ENV !== 'dev';
const WEBPACK_DEV_MODE = process.env.WEBPACK_DEV_MODE === '1';
const WEBPACK_REPORT = process.env.WEBPACK_REPORT;
const ROOT_PATH = path.resolve(__dirname, '../../');
const webpackConfig = {
mode: IS_PRODUCTION ? 'production' : 'development',
target: 'web',
var webpackConfig = {
entry: {
default: [path.resolve(path.join(__dirname, './default'))],
'router-nli-app': path.resolve(path.join(__dirname, './router-nli-app.js')),
'router-nli-chat': path.resolve(path.join(__dirname, './router-nli-chat.js')),
'router-app': path.resolve(path.join(__dirname, './router-app.js')),
......@@ -35,28 +47,7 @@ var webpackConfig = {
'chat-message-reports': path.resolve(path.join(__dirname, './chat-message-reports.js')),
'mobile-native-userhome': path.resolve(path.join(__dirname, './mobile-native-userhome')),
'router-home-learn': path.resolve(path.join(__dirname, './router-home-learn')),
vendor: [
require.resolve('./utils/webpack'),
require.resolve('./utils/context'),
'underscore',
'jquery',
'backbone',
'backbone.marionette',
'loglevel',
require.resolve('./utils/log'),
require.resolve('./components/api-client'),
'handlebars/runtime',
'gitter-realtime-client',
'raven-js',
'keymaster',
'moment',
'bluebird',
'fuzzysearch',
'url-join',
path.resolve(path.join(__dirname, './commons.js'))
]
'router-home-learn': path.resolve(path.join(__dirname, './router-home-learn'))
},
output: {
path: path.resolve(__dirname, '../../output/assets/js/'),
......@@ -67,17 +58,14 @@ var webpackConfig = {
devtoolFallbackModuleFilenameTemplate: '[resource-path]?[hash]'
},
module: {
//JP 12/1/16 If you add a loader remember to add it to /test/in-browser/webpack.config.js
loaders: [
strictExportPresence: true,
rules: [
{
test: /\.js?$/,
loader: 'babel',
test: /\.js$/,
loader: 'babel-loader',
exclude: [/node_modules/],
query: {
presets: [
// https://github.com/babel/babel-loader/issues/149
require.resolve('babel-preset-es2015')
]
options: {
presets: ['@babel/preset-env']
}
},
{
......@@ -93,7 +81,11 @@ var webpackConfig = {
},
{
test: /.css$/,
loader: 'style-loader?insertAt=top!css-loader!postcss-loader'
use: [
{ loader: 'style-loader', options: { insertAt: 'top' } },
{ loader: 'css-loader', options: { importLoaders: 1 } },
{ loader: 'postcss-loader', options: { plugins: getPostcssStack(webpack) } }
]
}
]
},
......@@ -122,21 +114,63 @@ var webpackConfig = {
bluebird: path.resolve(path.join(__dirname, 'utils/bluebird-wrapper'))
}
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
maxInitialRequests: 4,
cacheGroups: {
default: false,
vendor: {
name: 'vendor',
chunks: 'all',
// Minimum number of chunks that must share a module before splitting
minChunks: 2,
// `d3` is only used by `@gitterhq/cal-heatmap` so let's put it in the specific archive chunk
test: /[\\/]node_modules[\\/](?!d3)/
}
}
}
},
plugins: [
// TODO: Use this in the future to for the bootScript in `hbs-helpers.js`
// and `sub-resources.js`. See how GitLab does it
// https://gitlab.com/gitlab-org/gitlab-ce/blob/dd26a9addc5dd654e3c8eecb58216f1f4449cfc1/lib/gitlab/webpack/manifest.rb
// https://gitlab.com/gitlab-org/gitlab-ce/blob/dd26a9addc5dd654e3c8eecb58216f1f4449cfc1/app/helpers/webpack_helper.rb
new StatsWriterPlugin({
filename: 'webpack-manifest.json',
transform: function(data, opts) {
const stats = opts.compiler.getStats().toJson({
chunkModules: false,
source: false,
chunks: false,
modules: false,
assets: true
});
return JSON.stringify(stats, null, 2);
}
}),
new ProvidePlugin({ Promise: 'bluebird' }),
new CommonsChunkPlugin('vendor', '[name].js'),
new ContextReplacementPlugin(
/moment\/locale$/,
/moment[/\\]locale$/,
/ar|cs|da|de|en-gb|es|fa|fr|hu|it|ja|ko|lt|nl|pl|pt|ru|sk|sv|ua|zh-cn/
)
],
bail: true,
postcss: function(webpack) {
return getPostcssStack(webpack);
}
),
// optionally generate webpack bundle analysis
WEBPACK_REPORT &&
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')
})
].filter(Boolean),
bail: true
};
if (devMode) {
if (WEBPACK_DEV_MODE) {
// See http://webpack.github.io/docs/configuration.html#devtool
webpackConfig.devtool = 'cheap-source-map';
webpackConfig.cache = true;
......@@ -149,14 +183,4 @@ if (process.env.WEBPACK_VISUALIZER) {
webpackConfig.plugins.push(new Visualizer({ filename: '../../webpack.stats.html' }));
}
if (process.env.WEBPACK_STATS) {
var StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin;
webpackConfig.plugins.push(
new StatsWriterPlugin({
filename: '../../webpack.stats.json',
fields: null
})
);
}
module.exports = webpackConfig;
......@@ -3,9 +3,9 @@
var cdn = require('gitter-web-cdn');
function cdnSubResources(resources, jsRoot) {
var resourceList = ['vendor'];
var resourceList = ['runtime', 'default.chunk', 'vendor.chunk'];
if (resources) {
resourceList = resourceList.concat(resources);
resourceList = resourceList.concat(resources.map(resource => `${resource}.chunk`));
}
return resourceList
......
......@@ -12,8 +12,7 @@ exports.install = function(app) {
app.use(
webpackMiddleware(webpack(require('../../public/js/webpack.config')), {
noInfo: false,
quiet: true,
logLevel: 'warn',
lazy: false,
watchOptions: {
aggregateTimeout: 400
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment