blob: 0d751d32db65b9e3fde40cf9a94aff0e46426ed9 [file] [log] [blame]
// Copyright 2020 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'cypress';
import 'webpack-dev-server';
import fs from 'fs';
import { createProxyMiddleware } from 'http-proxy-middleware';
import path from 'path';
import { DefinePlugin } from 'webpack';
import merge from 'webpack-merge';
import Workbox from 'workbox-webpack-plugin';
import common from './webpack.common';
const cypressConfig: Cypress.ConfigOptions = require('./cypress.json');
const DEBUG_SW = process.env.DEBUG_SW === 'true';
export default merge(common, {
mode: 'development',
devtool: 'eval-source-map',
// Service workers makes live/hot reload harder, so it should be disabled by
// default in dev mode.
plugins: [
new DefinePlugin({
IS_DEV: JSON.stringify(true),
ENABLE_UI_SW: JSON.stringify(DEBUG_SW),
}),
...(DEBUG_SW
? [
new Workbox.GenerateSW({
// Without this, new release will not take effect until users close
// all build page tabs.
skipWaiting: true,
navigateFallback: '/ui/index.html',
sourcemap: true,
importScriptsViaChunks: ['service-worker-ext'],
// Set to 5 MB to suppress the warning in dev mode.
// Dev bundles are naturally larger as they have inline source maps.
maximumFileSizeToCacheInBytes: 5242880,
}),
]
: []),
],
devServer: {
hot: false,
// Live reload causes the page to enter refresh loop when debugging SW.
liveReload: !DEBUG_SW,
client: {
overlay: false,
},
static: {
directory: path.join(__dirname, './out/'),
},
historyApiFallback: {
index: '/ui/index.html',
},
port: Number(new URL(cypressConfig.baseUrl || 'https://localhost:8080').port),
setupMiddlewares: (middlewares, devServer) => {
// This won't happen, but it helps TSC infer the type.
if (!devServer.app) {
throw new Error('app not initialized');
}
devServer.app.use((req, _res, next) => {
// Host root-sw.js at root so it can have root scope.
if (/^\/(root-sw\.js(\.map)?)$/.test(req.path)) {
req.url = req.url.slice(0, req.url.length - req.path.length) + '/ui' + req.path;
}
next();
});
devServer.app.get('/configs.js', async (_req, res) => {
res.set('content-type', 'application/javascript');
const appConfigs = JSON.parse(fs.readFileSync(path.join(__dirname, 'dev-configs/configs.json'), 'utf8'));
const configsTemplate = fs.readFileSync(path.join(__dirname, 'assets/configs.template.js'), 'utf8');
const config = configsTemplate
.replace('{{.ResultDB.Host}}', appConfigs.RESULT_DB.HOST)
.replace('{{.Buildbucket.Host}}', appConfigs.BUILDBUCKET.HOST)
.replace('{{.Weetbix.Host}}', appConfigs.WEETBIX.HOST);
res.send(config);
});
devServer.app.use(
/^(?!\/ui\/).*/,
createProxyMiddleware({
// This attribute is required. However the value will be overridden by
// the router option. So the value doesn't matter.
target: 'https://luci-milo-dev.appspot.com',
router: () => {
const localDevConfigs = JSON.parse(
fs.readFileSync(path.join(__dirname, 'dev-configs/local-dev-configs.json'), 'utf8')
);
return localDevConfigs.milo.url;
},
changeOrigin: true,
secure: false,
})
);
return middlewares;
},
},
});