feat(load-test) split to a separate repository
It now lives here https://github.com/jitsi/jitsi-meet-load-test
This commit is contained in:
parent
a7abe84479
commit
0b57bcb20b
|
@ -3,11 +3,9 @@ build/*
|
|||
|
||||
# Third-party source code which we (1) do not want to modify or (2) try to
|
||||
# modify as little as possible.
|
||||
flow-typed/*
|
||||
libs/*
|
||||
resources/*
|
||||
react/features/stream-effects/virtual-background/vendor/*
|
||||
load-test/*
|
||||
react/features/face-landmarks/resources/*
|
||||
|
||||
# ESLint will by default ignore its own configuration file. However, there does
|
||||
|
|
5
Makefile
5
Makefile
|
@ -19,12 +19,9 @@ WEBPACK_DEV_SERVER = ./node_modules/.bin/webpack serve --mode development
|
|||
|
||||
all: compile deploy clean
|
||||
|
||||
compile: compile-load-test
|
||||
compile:
|
||||
$(WEBPACK)
|
||||
|
||||
compile-load-test:
|
||||
${NPM} install --prefix resources/load-test && ${NPM} run build --prefix resources/load-test
|
||||
|
||||
clean:
|
||||
rm -fr $(BUILD_DIR)
|
||||
|
||||
|
|
|
@ -14,5 +14,3 @@ resources/robots.txt /usr/share/jitsi-meet/
|
|||
resources/*.sh /usr/share/jitsi-meet/scripts/
|
||||
pwa-worker.js /usr/share/jitsi-meet/
|
||||
manifest.json /usr/share/jitsi-meet/
|
||||
resources/load-test/*.html /usr/share/jitsi-meet/load-test/
|
||||
resources/load-test/libs /usr/share/jitsi-meet/load-test/
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head lang="en">
|
||||
<meta charset="UTF-8">
|
||||
<title></title>
|
||||
<script><!--#include virtual="/config.js" --></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
|
||||
<script src="../libs/lib-jitsi-meet.min.js?v=139"></script>
|
||||
<script src="libs/load-test-participant.min.js" ></script>
|
||||
</head>
|
||||
<body>
|
||||
<div>Number of participants: <span id="participants">1</span></div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,523 +0,0 @@
|
|||
/* global $, config, JitsiMeetJS */
|
||||
import 'jquery';
|
||||
import { setConfigFromURLParams } from '../../react/features/base/config/functions';
|
||||
import { parseURLParams } from '../../react/features/base/util/parseURLParams';
|
||||
import { parseURIString } from '../../react/features/base/util/uri';
|
||||
import { validateLastNLimits, limitLastN } from '../../react/features/base/lastn/functions';
|
||||
|
||||
setConfigFromURLParams(config, {}, {}, window.location);
|
||||
|
||||
const params = parseURLParams(window.location, false, 'hash');
|
||||
const { isHuman = false } = params;
|
||||
const {
|
||||
localVideo = config.startWithVideoMuted !== true,
|
||||
remoteVideo = isHuman,
|
||||
remoteAudio = isHuman,
|
||||
autoPlayVideo = config.testing.noAutoPlayVideo !== true,
|
||||
stageView = config.disableTileView,
|
||||
numClients = 1,
|
||||
clientInterval = 100 // ms
|
||||
} = params;
|
||||
|
||||
let {
|
||||
localAudio = config.startWithAudioMuted !== true,
|
||||
} = params;
|
||||
|
||||
const { room: roomName } = parseURIString(window.location.toString());
|
||||
|
||||
class LoadTestClient {
|
||||
constructor(id) {
|
||||
this.id = id;
|
||||
this.connection = null;
|
||||
this.connected = false;
|
||||
this.room = null;
|
||||
this.numParticipants = 1;
|
||||
this.localTracks = [];
|
||||
this.remoteTracks = {};
|
||||
this.maxFrameHeight = 0;
|
||||
this.selectedParticipant = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple emulation of jitsi-meet's screen layout behavior
|
||||
*/
|
||||
updateMaxFrameHeight() {
|
||||
if (!this.connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newMaxFrameHeight;
|
||||
|
||||
if (stageView) {
|
||||
newMaxFrameHeight = 2160;
|
||||
}
|
||||
else {
|
||||
if (this.numParticipants <= 2) {
|
||||
newMaxFrameHeight = 720;
|
||||
} else if (this.numParticipants <= 4) {
|
||||
newMaxFrameHeight = 360;
|
||||
} else {
|
||||
this.newMaxFrameHeight = 180;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.room && this.maxFrameHeight !== newMaxFrameHeight) {
|
||||
this.maxFrameHeight = newMaxFrameHeight;
|
||||
this.room.setReceiverVideoConstraint(this.maxFrameHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple emulation of jitsi-meet's lastN behavior
|
||||
*/
|
||||
updateLastN() {
|
||||
if (!this.connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
let lastN = typeof config.channelLastN === 'undefined' ? -1 : config.channelLastN;
|
||||
|
||||
const limitedLastN = limitLastN(this.numParticipants, validateLastNLimits(config.lastNLimits));
|
||||
|
||||
if (limitedLastN !== undefined) {
|
||||
lastN = lastN === -1 ? limitedLastN : Math.min(limitedLastN, lastN);
|
||||
}
|
||||
|
||||
if (lastN === this.room.getLastN()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.room.setLastN(lastN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to query whether a participant ID is a valid ID
|
||||
* for stage view.
|
||||
*/
|
||||
isValidStageViewParticipant(id) {
|
||||
return (id !== room.myUserId() && room.getParticipantById(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple emulation of jitsi-meet's stage view participant selection behavior.
|
||||
* Doesn't take into account pinning or screen sharing, and the initial behavior
|
||||
* is slightly different.
|
||||
* @returns Whether the selected participant changed.
|
||||
*/
|
||||
selectStageViewParticipant(selected, previous) {
|
||||
let newSelectedParticipant;
|
||||
|
||||
if (this.isValidStageViewParticipant(selected)) {
|
||||
newSelectedParticipant = selected;
|
||||
}
|
||||
else {
|
||||
newSelectedParticipant = previous.find(isValidStageViewParticipant);
|
||||
}
|
||||
if (newSelectedParticipant && newSelectedParticipant !== this.selectedParticipant) {
|
||||
this.selectedParticipant = newSelectedParticipant;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple emulation of jitsi-meet's selectParticipants behavior
|
||||
*/
|
||||
selectParticipants() {
|
||||
if (!this.connected) {
|
||||
return;
|
||||
}
|
||||
if (stageView) {
|
||||
if (this.selectedParticipant) {
|
||||
this.room.selectParticipants([this.selectedParticipant]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* jitsi-meet's current Tile View behavior. */
|
||||
const ids = this.room.getParticipants().map(participant => participant.getId());
|
||||
this.room.selectParticipants(ids);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when number of participants changes.
|
||||
*/
|
||||
setNumberOfParticipants() {
|
||||
if (this.id === 0) {
|
||||
$('#participants').text(this.numParticipants);
|
||||
}
|
||||
if (!stageView) {
|
||||
this.selectParticipants();
|
||||
this.updateMaxFrameHeight();
|
||||
}
|
||||
this.updateLastN();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when ICE connects
|
||||
*/
|
||||
onConnectionEstablished() {
|
||||
this.connected = true;
|
||||
|
||||
this.selectParticipants();
|
||||
this.updateMaxFrameHeight();
|
||||
this.updateLastN();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles dominant speaker changed.
|
||||
* @param id
|
||||
*/
|
||||
onDominantSpeakerChanged(selected, previous) {
|
||||
if (this.selectStageViewParticipant(selected, previous)) {
|
||||
this.selectParticipants();
|
||||
}
|
||||
this.updateMaxFrameHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles local tracks.
|
||||
* @param tracks Array with JitsiTrack objects
|
||||
*/
|
||||
onLocalTracks(tracks = []) {
|
||||
this.localTracks = tracks;
|
||||
for (let i = 0; i < this.localTracks.length; i++) {
|
||||
if (this.localTracks[i].getType() === 'video') {
|
||||
if (this.id === 0) {
|
||||
$('body').append(`<video ${autoPlayVideo ? 'autoplay="1" ' : ''}id='localVideo${i}' />`);
|
||||
this.localTracks[i].attach($(`#localVideo${i}`)[0]);
|
||||
}
|
||||
|
||||
this.room.addTrack(this.localTracks[i]);
|
||||
} else {
|
||||
if (localAudio) {
|
||||
this.room.addTrack(this.localTracks[i]);
|
||||
} else {
|
||||
this.localTracks[i].mute();
|
||||
}
|
||||
|
||||
if (this.id === 0) {
|
||||
$('body').append(
|
||||
`<audio autoplay='1' muted='true' id='localAudio${i}' />`);
|
||||
this.localTracks[i].attach($(`#localAudio${i}`)[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles remote tracks
|
||||
* @param track JitsiTrack object
|
||||
*/
|
||||
onRemoteTrack(track) {
|
||||
if (track.isLocal()
|
||||
|| (track.getType() === 'video' && !remoteVideo) || (track.getType() === 'audio' && !remoteAudio)) {
|
||||
return;
|
||||
}
|
||||
const participant = track.getParticipantId();
|
||||
|
||||
if (!this.remoteTracks[participant]) {
|
||||
this.remoteTracks[participant] = [];
|
||||
}
|
||||
|
||||
if (this.id !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const idx = this.remoteTracks[participant].push(track);
|
||||
const id = participant + track.getType() + idx;
|
||||
|
||||
if (track.getType() === 'video') {
|
||||
$('body').append(`<video autoplay='1' id='${id}' />`);
|
||||
} else {
|
||||
$('body').append(`<audio autoplay='1' id='${id}' />`);
|
||||
}
|
||||
track.attach($(`#${id}`)[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* That function is executed when the conference is joined
|
||||
*/
|
||||
onConferenceJoined() {
|
||||
console.log(`Participant ${this.id} Conference joined`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles start muted events, when audio and/or video are muted due to
|
||||
* startAudioMuted or startVideoMuted policy.
|
||||
*/
|
||||
onStartMuted() {
|
||||
// Give it some time, as it may be currently in the process of muting
|
||||
setTimeout(() => {
|
||||
const localAudioTrack = this.room.getLocalAudioTrack();
|
||||
|
||||
if (localAudio && localAudioTrack && localAudioTrack.isMuted()) {
|
||||
localAudioTrack.unmute();
|
||||
}
|
||||
|
||||
const localVideoTrack = this.room.getLocalVideoTrack();
|
||||
|
||||
if (localVideo && localVideoTrack && localVideoTrack.isMuted()) {
|
||||
localVideoTrack.unmute();
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
onUserJoined(id) {
|
||||
this.numParticipants++;
|
||||
this.setNumberOfParticipants();
|
||||
this.remoteTracks[id] = [];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
onUserLeft(id) {
|
||||
this.numParticipants--;
|
||||
this.setNumberOfParticipants();
|
||||
if (!this.remoteTracks[id]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.id !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tracks = this.remoteTracks[id];
|
||||
|
||||
for (let i = 0; i < tracks.length; i++) {
|
||||
const container = $(`#${id}${tracks[i].getType()}${i + 1}`)[0];
|
||||
|
||||
if (container) {
|
||||
tracks[i].detach(container);
|
||||
container.parentElement.removeChild(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles private messages.
|
||||
*
|
||||
* @param {string} id - The sender ID.
|
||||
* @param {string} text - The message.
|
||||
* @returns {void}
|
||||
*/
|
||||
onPrivateMessage(id, text) {
|
||||
switch (text) {
|
||||
case 'video on':
|
||||
this.onVideoOnMessage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles 'video on' private messages.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
onVideoOnMessage() {
|
||||
console.debug(`Participant ${this.id}: Turning my video on!`);
|
||||
|
||||
const localVideoTrack = this.room.getLocalVideoTrack();
|
||||
|
||||
if (localVideoTrack && localVideoTrack.isMuted()) {
|
||||
console.debug(`Participant ${this.id}: Unmuting existing video track.`);
|
||||
localVideoTrack.unmute();
|
||||
} else if (!localVideoTrack) {
|
||||
JitsiMeetJS.createLocalTracks({ devices: ['video'] })
|
||||
.then(([videoTrack]) => videoTrack)
|
||||
.catch(console.error)
|
||||
.then(videoTrack => {
|
||||
return this.room.replaceTrack(null, videoTrack);
|
||||
})
|
||||
.then(() => {
|
||||
console.debug(`Participant ${this.id}: Successfully added a new video track for unmute.`);
|
||||
});
|
||||
} else {
|
||||
console.log(`Participant ${this.id}: No-op! We are already video unmuted!`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called to connect.
|
||||
*/
|
||||
connect() {
|
||||
this._onConnectionSuccess = this.onConnectionSuccess.bind(this)
|
||||
this._onConnectionFailed = this.onConnectionFailed.bind(this)
|
||||
this._disconnect = this.disconnect.bind(this)
|
||||
|
||||
this.connection = new JitsiMeetJS.JitsiConnection(null, null, config);
|
||||
this.connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED, this._onConnectionSuccess);
|
||||
this.connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_FAILED, this._onConnectionFailed);
|
||||
this.connection.addEventListener(JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED, this._disconnect);
|
||||
this.connection.connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* That function is called when connection is established successfully
|
||||
*/
|
||||
onConnectionSuccess() {
|
||||
this.room = this.connection.initJitsiConference(roomName.toLowerCase(), config);
|
||||
this.room.on(JitsiMeetJS.events.conference.STARTED_MUTED, this.onStartMuted.bind(this));
|
||||
this.room.on(JitsiMeetJS.events.conference.TRACK_ADDED, this.onRemoteTrack.bind(this));
|
||||
this.room.on(JitsiMeetJS.events.conference.CONFERENCE_JOINED, this.onConferenceJoined.bind(this));
|
||||
this.room.on(JitsiMeetJS.events.conference.CONNECTION_ESTABLISHED, this.onConnectionEstablished.bind(this));
|
||||
this.room.on(JitsiMeetJS.events.conference.USER_JOINED, this.onUserJoined.bind(this));
|
||||
this.room.on(JitsiMeetJS.events.conference.USER_LEFT, this.onUserLeft.bind(this));
|
||||
this.room.on(JitsiMeetJS.events.conference.PRIVATE_MESSAGE_RECEIVED, this.onPrivateMessage.bind(this));
|
||||
if (stageView) {
|
||||
this.room.on(JitsiMeetJS.events.conference.DOMINANT_SPEAKER_CHANGED, this.onDominantSpeakerChanged.bind(this));
|
||||
}
|
||||
|
||||
const devices = [];
|
||||
|
||||
if (localVideo) {
|
||||
devices.push('video');
|
||||
}
|
||||
|
||||
// we always create audio local tracks
|
||||
devices.push('audio');
|
||||
|
||||
if (devices.length > 0) {
|
||||
JitsiMeetJS.createLocalTracks({ devices })
|
||||
.then(this.onLocalTracks.bind(this))
|
||||
.then(() => {
|
||||
this.room.join();
|
||||
})
|
||||
.catch(error => {
|
||||
throw error;
|
||||
});
|
||||
} else {
|
||||
this.room.join();
|
||||
}
|
||||
|
||||
this.updateMaxFrameHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when the connection fail.
|
||||
*/
|
||||
onConnectionFailed() {
|
||||
console.error(`Participant ${this.id}: Connection Failed!`);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when we disconnect.
|
||||
*/
|
||||
disconnect() {
|
||||
console.log('disconnect!');
|
||||
this.connection.removeEventListener(
|
||||
JitsiMeetJS.events.connection.CONNECTION_ESTABLISHED,
|
||||
this._onConnectionSuccess);
|
||||
this.connection.removeEventListener(
|
||||
JitsiMeetJS.events.connection.CONNECTION_FAILED,
|
||||
this._onConnectionFailed);
|
||||
this.connection.removeEventListener(
|
||||
JitsiMeetJS.events.connection.CONNECTION_DISCONNECTED,
|
||||
this._disconnect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let clients = [];
|
||||
|
||||
window.APP = {
|
||||
conference: {
|
||||
getStats() {
|
||||
return clients[0]?.room?.connectionQuality.getStats();
|
||||
},
|
||||
getConnectionState() {
|
||||
return clients[0] && clients[0].room && room.getConnectionState();
|
||||
},
|
||||
muteAudio(mute) {
|
||||
localAudio = mute;
|
||||
for (let j = 0; j < clients.length; j++) {
|
||||
for (let i = 0; i < clients[j].localTracks.length; i++) {
|
||||
if (clients[j].localTracks[i].getType() === 'audio') {
|
||||
if (mute) {
|
||||
clients[j].localTracks[i].mute();
|
||||
}
|
||||
else {
|
||||
clients[j].localTracks[i].unmute();
|
||||
|
||||
// if track was not added we need to add it to the peerconnection
|
||||
if (!clients[j].room.getLocalAudioTrack()) {
|
||||
clients[j].room.replaceTrack(null, clients[j].localTracks[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
get room() {
|
||||
return clients[0]?.room;
|
||||
},
|
||||
get connection() {
|
||||
return clients[0]?.connection;
|
||||
},
|
||||
get numParticipants() {
|
||||
return clients[0]?.remoteParticipants;
|
||||
},
|
||||
get localTracks() {
|
||||
return clients[0]?.localTracks;
|
||||
},
|
||||
get remoteTracks() {
|
||||
return clients[0]?.remoteTracks;
|
||||
},
|
||||
get params() {
|
||||
return {
|
||||
roomName,
|
||||
localAudio,
|
||||
localVideo,
|
||||
remoteVideo,
|
||||
remoteAudio,
|
||||
autoPlayVideo,
|
||||
stageView
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function unload() {
|
||||
for (let j = 0; j < clients.length; j++) {
|
||||
for (let i = 0; i < clients[j].localTracks.length; i++) {
|
||||
clients[j].localTracks[i].dispose();
|
||||
}
|
||||
clients[j].room.leave();
|
||||
clients[j].connection.disconnect();
|
||||
}
|
||||
clients = [];
|
||||
}
|
||||
|
||||
$(window).bind('beforeunload', unload);
|
||||
$(window).bind('unload', unload);
|
||||
|
||||
JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.ERROR);
|
||||
|
||||
JitsiMeetJS.init(config);
|
||||
|
||||
config.serviceUrl = config.bosh = `${config.websocket || config.bosh}?room=${roomName.toLowerCase()}`;
|
||||
if (config.websocketKeepAliveUrl) {
|
||||
config.websocketKeepAliveUrl += `?room=${roomName.toLowerCase()}`;
|
||||
}
|
||||
|
||||
function startClient(i) {
|
||||
clients[i] = new LoadTestClient(i);
|
||||
clients[i].connect();
|
||||
if (i + 1 < numClients) {
|
||||
setTimeout(() => { startClient(i+1) }, clientInterval)
|
||||
}
|
||||
}
|
||||
|
||||
if (numClients > 0) {
|
||||
startClient(0)
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,56 +0,0 @@
|
|||
{
|
||||
"name": "jitsi-meet-load-test",
|
||||
"version": "0.0.0",
|
||||
"description": "A load test participant",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/jitsi/jitsi-meet"
|
||||
},
|
||||
"keywords": [
|
||||
"jingle",
|
||||
"webrtc",
|
||||
"xmpp",
|
||||
"browser"
|
||||
],
|
||||
"author": "",
|
||||
"readmeFilename": "../README.md",
|
||||
"dependencies": {
|
||||
"jquery": "3.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.5.5",
|
||||
"@babel/plugin-proposal-class-properties": "7.1.0",
|
||||
"@babel/plugin-proposal-export-default-from": "7.0.0",
|
||||
"@babel/plugin-proposal-export-namespace-from": "7.0.0",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "7.4.4",
|
||||
"@babel/plugin-proposal-optional-chaining": "7.2.0",
|
||||
"@babel/plugin-transform-flow-strip-types": "7.0.0",
|
||||
"@babel/preset-env": "7.1.0",
|
||||
"@babel/preset-flow": "7.0.0",
|
||||
"@babel/runtime": "7.5.5",
|
||||
"babel-eslint": "10.0.1",
|
||||
"babel-loader": "8.0.4",
|
||||
"eslint": "5.6.1",
|
||||
"eslint-config-jitsi": "github:jitsi/eslint-config-jitsi#1.0.3",
|
||||
"eslint-plugin-flowtype": "2.50.3",
|
||||
"eslint-plugin-import": "2.20.2",
|
||||
"eslint-plugin-jsdoc": "3.8.0",
|
||||
"expose-loader": "0.7.5",
|
||||
"flow-bin": "0.104.0",
|
||||
"imports-loader": "0.7.1",
|
||||
"lodash": "4.17.21",
|
||||
"string-replace-loader": "2.1.1",
|
||||
"style-loader": "0.19.0",
|
||||
"webpack": "4.43.0",
|
||||
"webpack-bundle-analyzer": "3.4.1",
|
||||
"webpack-cli": "3.3.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0",
|
||||
"npm": ">=6.0.0"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"build": "webpack -p"
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
/* global __dirname */
|
||||
|
||||
const process = require('process');
|
||||
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
||||
const analyzeBundle = process.argv.indexOf('--analyze-bundle') !== -1;
|
||||
const minimize
|
||||
= process.argv.indexOf('-p') !== -1
|
||||
|| process.argv.indexOf('--optimize-minimize') !== -1;
|
||||
|
||||
/**
|
||||
* Build a Performance configuration object for the given size.
|
||||
* See: https://webpack.js.org/configuration/performance/
|
||||
*/
|
||||
function getPerformanceHints(size) {
|
||||
return {
|
||||
hints: minimize ? 'error' : false,
|
||||
maxAssetSize: size,
|
||||
maxEntrypointSize: size
|
||||
};
|
||||
}
|
||||
|
||||
// The base Webpack configuration to bundle the JavaScript artifacts of
|
||||
// jitsi-meet such as app.bundle.js and external_api.js.
|
||||
const config = {
|
||||
devtool: 'source-map',
|
||||
mode: minimize ? 'production' : 'development',
|
||||
module: {
|
||||
rules: [ {
|
||||
// Transpile ES2015 (aka ES6) to ES5. Accept the JSX syntax by React
|
||||
// as well.
|
||||
|
||||
exclude: [
|
||||
new RegExp(`${__dirname}/node_modules/(?!js-utils)`)
|
||||
],
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
// XXX The require.resolve bellow solves failures to locate the
|
||||
// presets when lib-jitsi-meet, for example, is npm linked in
|
||||
// jitsi-meet.
|
||||
plugins: [
|
||||
require.resolve('@babel/plugin-transform-flow-strip-types'),
|
||||
require.resolve('@babel/plugin-proposal-class-properties'),
|
||||
require.resolve('@babel/plugin-proposal-export-default-from'),
|
||||
require.resolve('@babel/plugin-proposal-export-namespace-from'),
|
||||
require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
|
||||
require.resolve('@babel/plugin-proposal-optional-chaining')
|
||||
],
|
||||
presets: [
|
||||
[
|
||||
require.resolve('@babel/preset-env'),
|
||||
|
||||
// Tell babel to avoid compiling imports into CommonJS
|
||||
// so that webpack may do tree shaking.
|
||||
{
|
||||
modules: false,
|
||||
|
||||
// Specify our target browsers so no transpiling is
|
||||
// done unnecessarily. For browsers not specified
|
||||
// here, the ES2015+ profile will be used.
|
||||
targets: {
|
||||
chrome: 58,
|
||||
electron: 2,
|
||||
firefox: 54,
|
||||
safari: 11
|
||||
}
|
||||
|
||||
}
|
||||
],
|
||||
require.resolve('@babel/preset-flow'),
|
||||
require.resolve('@babel/preset-react')
|
||||
]
|
||||
},
|
||||
test: /\.jsx?$/
|
||||
}, {
|
||||
// Expose jquery as the globals $ and jQuery because it is expected
|
||||
// to be available in such a form by multiple jitsi-meet
|
||||
// dependencies including lib-jitsi-meet.
|
||||
|
||||
loader: 'expose-loader?$!expose-loader?jQuery',
|
||||
test: /\/node_modules\/jquery\/.*\.js$/
|
||||
} ]
|
||||
},
|
||||
node: {
|
||||
// Allow the use of the real filename of the module being executed. By
|
||||
// default Webpack does not leak path-related information and provides a
|
||||
// value that is a mock (/index.js).
|
||||
__filename: true
|
||||
},
|
||||
optimization: {
|
||||
concatenateModules: minimize,
|
||||
minimize
|
||||
},
|
||||
output: {
|
||||
filename: `[name]${minimize ? '.min' : ''}.js`,
|
||||
path: `${__dirname}/libs`,
|
||||
publicPath: 'load-test/libs/',
|
||||
sourceMapFilename: `[name].${minimize ? 'min' : 'js'}.map`
|
||||
},
|
||||
plugins: [
|
||||
analyzeBundle
|
||||
&& new BundleAnalyzerPlugin({
|
||||
analyzerMode: 'disabled',
|
||||
generateStatsFile: true
|
||||
})
|
||||
].filter(Boolean),
|
||||
resolve: {
|
||||
alias: {
|
||||
jquery: `jquery/dist/jquery${minimize ? '.min' : ''}.js`
|
||||
},
|
||||
aliasFields: [
|
||||
'browser'
|
||||
],
|
||||
extensions: [
|
||||
'.web.js',
|
||||
|
||||
// Webpack defaults:
|
||||
'.js',
|
||||
'.json'
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = [
|
||||
Object.assign({}, config, {
|
||||
entry: {
|
||||
'load-test-participant': './load-test-participant.js'
|
||||
},
|
||||
performance: getPerformanceHints(3 * 1024 * 1024)
|
||||
})
|
||||
];
|
||||
|
Loading…
Reference in New Issue