Remove Webpack dev servers for Boards/Playbooks (#23378)
* Add option to run web app build without dev servers * Completely remove product dev servers * Update unit test * Fix another test
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
e1a2443f1a
Коммит
4cbf6e93d2
@@ -8,7 +8,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
@@ -132,25 +131,6 @@ func generateDevCSP(c Context) string {
|
||||
}
|
||||
}
|
||||
|
||||
// Add flags for Webpack dev servers used by other products during development
|
||||
if model.BuildNumber == "dev" {
|
||||
boardsURL := os.Getenv("MM_BOARDS_DEV_SERVER_URL")
|
||||
if boardsURL == "" {
|
||||
// Focalboard runs on http://localhost:9006 by default
|
||||
boardsURL = "http://localhost:9006"
|
||||
}
|
||||
|
||||
devCSP = append(devCSP, boardsURL)
|
||||
|
||||
playbooksURL := os.Getenv("MM_PLAYBOOKS_DEV_SERVER_URL")
|
||||
if playbooksURL == "" {
|
||||
// Playbooks runs on http://localhost:9007 by default
|
||||
playbooksURL = "http://localhost:9007"
|
||||
}
|
||||
|
||||
devCSP = append(devCSP, playbooksURL)
|
||||
}
|
||||
|
||||
if len(devCSP) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -449,7 +449,7 @@ func TestHandlerServeCSPHeader(t *testing.T) {
|
||||
response := httptest.NewRecorder()
|
||||
handler.ServeHTTP(response, request)
|
||||
assert.Equal(t, 200, response.Code)
|
||||
assert.Equal(t, []string{"frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com js.stripe.com/v3 'unsafe-eval' 'unsafe-inline' http://localhost:9006 http://localhost:9007"}, response.Header()["Content-Security-Policy"])
|
||||
assert.Equal(t, []string{"frame-ancestors 'self'; script-src 'self' cdn.rudderlabs.com js.stripe.com/v3 'unsafe-eval' 'unsafe-inline'"}, response.Header()["Content-Security-Policy"])
|
||||
})
|
||||
|
||||
}
|
||||
@@ -472,7 +472,7 @@ func TestGenerateDevCSP(t *testing.T) {
|
||||
|
||||
devCSP := generateDevCSP(*c)
|
||||
|
||||
assert.Equal(t, " 'unsafe-eval' 'unsafe-inline' http://localhost:9006 http://localhost:9007", devCSP)
|
||||
assert.Equal(t, " 'unsafe-eval' 'unsafe-inline'", devCSP)
|
||||
})
|
||||
|
||||
t.Run("allowed dev flags", func(t *testing.T) {
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
"scripts": {
|
||||
"build": "webpack --mode=production",
|
||||
"build:watch": "webpack --mode=production --watch",
|
||||
"start:product": "webpack serve --mode=development",
|
||||
"debug": "webpack --mode=none",
|
||||
"debug:watch": "webpack --mode=development --watch",
|
||||
"start:product": "webpack --mode=development --watch",
|
||||
"check-lint": "eslint --ignore-pattern ../.git-ignore --ignore-pattern dist --ext js,jsx,tsx,ts . --quiet --cache",
|
||||
"check-lint:fix": "npm run check-lint -- --fix",
|
||||
"check-style": "stylelint **/*.scss",
|
||||
|
||||
@@ -186,36 +186,4 @@ config.plugins.push(new MiniCssExtractPlugin({
|
||||
chunkFilename: '[name].[contenthash].css',
|
||||
}));
|
||||
|
||||
if (NPM_TARGET === 'start:product') {
|
||||
const url = new URL(process.env.MM_BOARDS_DEV_SERVER_URL ?? 'http://localhost:9006');
|
||||
|
||||
const protocol = url.protocol.substring(0, url.protocol.length - 1);
|
||||
const hostname = url.hostname;
|
||||
let port = url.port;
|
||||
if (!port) {
|
||||
port = protocol === 'https' ? '443' : '80';
|
||||
}
|
||||
|
||||
config.devServer = {
|
||||
server: {
|
||||
type: protocol,
|
||||
options: {
|
||||
minVersion: process.env.MM_SERVICESETTINGS_TLSMINVER ?? 'TLSv1.2',
|
||||
key: process.env.MM_SERVICESETTINGS_TLSKEYFILE,
|
||||
cert: process.env.MM_SERVICESETTINGS_TLSCERTFILE,
|
||||
},
|
||||
},
|
||||
host: hostname,
|
||||
port,
|
||||
devMiddleware: {
|
||||
writeToDisk: false,
|
||||
},
|
||||
static: {
|
||||
directory: path.join(__dirname, 'static'),
|
||||
publicPath: '/static',
|
||||
},
|
||||
};
|
||||
}
|
||||
/* eslint-enable no-process-env */
|
||||
|
||||
module.exports = config;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
/* eslint-disable no-console, no-process-env */
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const url = require('url');
|
||||
@@ -29,9 +30,6 @@ const targetIsEslint = NPM_TARGET === 'check' || NPM_TARGET === 'fix' || process
|
||||
|
||||
const DEV = targetIsRun || targetIsStats || targetIsDevServer;
|
||||
|
||||
const boardsDevServerUrl = process.env.MM_BOARDS_DEV_SERVER_URL ?? 'http://localhost:9006';
|
||||
const playbooksDevServerUrl = process.env.MM_PLAYBOOKS_DEV_SERVER_URL ?? 'http://localhost:9007';
|
||||
|
||||
const STANDARD_EXCLUDE = [
|
||||
/node_modules/,
|
||||
];
|
||||
@@ -280,16 +278,34 @@ var config = {
|
||||
],
|
||||
};
|
||||
|
||||
if (DEV) {
|
||||
config.plugins.push({
|
||||
apply: (compiler) => {
|
||||
compiler.hooks.afterEmit.tap('AfterEmitPlugin', () => {
|
||||
const boardsDist = path.resolve(__dirname, '../boards/dist');
|
||||
const boardsSymlink = './dist/products/boards';
|
||||
const playbooksDist = path.resolve(__dirname, '../playbooks/dist');
|
||||
const playbooksSymlink = './dist/products/playbooks';
|
||||
|
||||
fs.mkdir('./dist/products', () => {
|
||||
if (!fs.existsSync(boardsSymlink)) {
|
||||
fs.symlinkSync(boardsDist, boardsSymlink, 'dir');
|
||||
}
|
||||
if (!fs.existsSync(playbooksSymlink)) {
|
||||
fs.symlinkSync(playbooksDist, playbooksSymlink, 'dir');
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function generateCSP() {
|
||||
let csp = 'script-src \'self\' cdn.rudderlabs.com/ js.stripe.com/v3';
|
||||
|
||||
if (DEV) {
|
||||
// react-hot-loader and development source maps require eval
|
||||
csp += ' \'unsafe-eval\'';
|
||||
|
||||
csp += ' ' + boardsDevServerUrl;
|
||||
|
||||
csp += ' ' + playbooksDevServerUrl;
|
||||
}
|
||||
|
||||
return csp;
|
||||
@@ -321,42 +337,19 @@ async function initializeModuleFederation() {
|
||||
|
||||
async function getRemoteContainers() {
|
||||
const products = [
|
||||
{name: 'boards', baseUrl: boardsDevServerUrl},
|
||||
{name: 'playbooks', baseUrl: playbooksDevServerUrl},
|
||||
{name: 'boards'},
|
||||
{name: 'playbooks'},
|
||||
];
|
||||
|
||||
const remotes = {};
|
||||
|
||||
if (process.env.MM_DONT_INCLUDE_PRODUCTS) {
|
||||
console.warn('Skipping initialization of products');
|
||||
} else if (DEV) {
|
||||
// For development, we use Webpack dev servers for each product
|
||||
for (const product of products) {
|
||||
remotes[product.name] = `${product.name}@${product.baseUrl}/remote_entry.js`;
|
||||
}
|
||||
} else {
|
||||
// For production, hardcode the URLs of product containers to be based on the web app URL
|
||||
for (const product of products) {
|
||||
remotes[product.name] = `${product.name}@[window.basename]/static/products/${product.name}/remote_entry.js?bt=${buildTimestamp}`;
|
||||
}
|
||||
}
|
||||
|
||||
const aliases = {};
|
||||
|
||||
for (const product of products) {
|
||||
if (remotes[product.name]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add false aliases to prevent Webpack from trying to resolve the missing modules
|
||||
aliases[product.name] = false;
|
||||
aliases[`${product.name}/manifest`] = false;
|
||||
remotes[product.name] = `${product.name}@[window.basename]/static/products/${product.name}/remote_entry.js?bt=${buildTimestamp}`;
|
||||
}
|
||||
|
||||
return {remotes, aliases};
|
||||
return {remotes};
|
||||
}
|
||||
|
||||
const {remotes, aliases} = await getRemoteContainers();
|
||||
const {remotes} = await getRemoteContainers();
|
||||
|
||||
const moduleFederationPluginOptions = {
|
||||
name: 'mattermost_webapp',
|
||||
@@ -404,11 +397,6 @@ async function initializeModuleFederation() {
|
||||
// Add this plugin to perform the substitution of window.basename when loading remote containers
|
||||
config.plugins.push(new ExternalTemplateRemotesPlugin());
|
||||
|
||||
config.resolve.alias = {
|
||||
...config.resolve.alias,
|
||||
...aliases,
|
||||
};
|
||||
|
||||
config.plugins.push(new webpack.DefinePlugin({
|
||||
REMOTE_CONTAINERS: JSON.stringify(remotes),
|
||||
}));
|
||||
|
||||
@@ -108,7 +108,6 @@
|
||||
"build:watch": "webpack --mode=production --watch",
|
||||
"debug": "webpack --mode=development",
|
||||
"debug:watch": "webpack --mode=development --watch",
|
||||
"dev-server": "webpack serve --mode=development",
|
||||
"check": "eslint --ignore-pattern node_modules --ignore-pattern dist --ext .js --ext .jsx --ext tsx --ext ts . --quiet --cache",
|
||||
"fix": "eslint --ignore-pattern node_modules --ignore-pattern dist --ext .js --ext .jsx --ext tsx --ext ts . --quiet --fix --cache",
|
||||
"test": "cross-env TZ=Etc/UTC jest",
|
||||
@@ -120,8 +119,7 @@
|
||||
"i18n-extract": "formatjs extract \"src/**/*.{ts,tsx}\" --ignore \"**/*.d.ts\" --id-interpolation-pattern '[sha512:contenthash:base64:6]' --format simple --out-file i18n/en.json",
|
||||
"graphql": "graphql-codegen --config graphql_gen.ts",
|
||||
"report-unused-exports": "ts-prune",
|
||||
"build:product": "webpack --mode=production",
|
||||
"start:product": "webpack serve --mode=development",
|
||||
"start:product": "webpack --mode=development --watch",
|
||||
"deploy:product": "node scripts/deploy.js",
|
||||
"clean": "rm -rf node_modules"
|
||||
}
|
||||
|
||||
@@ -133,31 +133,4 @@ config.output = {
|
||||
chunkFilename: '[name].[contenthash].js',
|
||||
};
|
||||
|
||||
if (NPM_TARGET === 'start:product') {
|
||||
const url = new URL(process.env.MM_PLAYBOOKS_DEV_SERVER_URL ?? 'http://localhost:9007');
|
||||
|
||||
const protocol = url.protocol.substring(0, url.protocol.length - 1);
|
||||
const hostname = url.hostname;
|
||||
let port = url.port;
|
||||
if (!port) {
|
||||
port = protocol === 'https' ? '443' : '80';
|
||||
}
|
||||
|
||||
config.devServer = {
|
||||
server: {
|
||||
type: protocol,
|
||||
options: {
|
||||
minVersion: process.env.MM_SERVICESETTINGS_TLSMINVER ?? 'TLSv1.2',
|
||||
key: process.env.MM_SERVICESETTINGS_TLSKEYFILE,
|
||||
cert: process.env.MM_SERVICESETTINGS_TLSCERTFILE,
|
||||
},
|
||||
},
|
||||
host: hostname,
|
||||
port,
|
||||
devMiddleware: {
|
||||
writeToDisk: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = config;
|
||||
|
||||
Ссылка в новой задаче
Block a user