Skip to content

Commit

Permalink
refactor(client): updated to latest module importing
Browse files Browse the repository at this point in the history
  • Loading branch information
knagaitsev committed Sep 25, 2019
1 parent ed5ee20 commit df594ad
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 98 deletions.
3 changes: 3 additions & 0 deletions client-src/default/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import { log, setLogLevel } from './utils/log';
import sendMessage from './utils/sendMessage';
import reloadApp from './utils/reloadApp';
import createSocketUrl from './utils/createSocketUrl';
import updatePublicPath from './utils/updatePublicPath';

updatePublicPath(__resourceQuery);

const status = {
isUnloading: false,
Expand Down
89 changes: 7 additions & 82 deletions client-src/default/utils/createSocketUrl.js
Original file line number Diff line number Diff line change
@@ -1,93 +1,18 @@
import url from 'url';
import querystring from 'querystring';
import getCurrentScriptSource from './getCurrentScriptSource';
import getUrlParts from './getUrlParts';

function createSocketUrl(resourceQuery) {
let urlParts;

if (typeof resourceQuery === 'string' && resourceQuery !== '') {
// If this bundle is inlined, use the resource query to get the correct url.
urlParts = url.parse(resourceQuery.substr(1));
} else {
// Else, get the url from the <script> this file was called with.
const scriptHost = getCurrentScriptSource();

// it seems the reg exp below was intended to cut off the path of a script source,
// so if you have my.host/long/path as the script source, it would become my.host.
// however, it did not work, because if you had http://my.host/long/path it would
// turn it into http:/. Cutting off the path is no longer needed, since we
// simply do url.parse and pull the host from there.

// eslint-disable-next-line no-useless-escape
// scriptHost = scriptHost.replace(/\/[^\/]+$/, '');
urlParts = url.parse(scriptHost || '/', false, true);
}

if (!urlParts.port || urlParts.port === '0') {
urlParts.port = self.location.port;
}

const { auth, path } = urlParts;
let { hostname, protocol } = urlParts;

// check ipv4 and ipv6 `all hostname`
// why do we need this check?
// hostname n/a for file protocol (example, when using electron, ionic)
// see: https://github.com/webpack/webpack-dev-server/pull/384
const isAnyHostname =
(hostname === '0.0.0.0' || hostname === '::') &&
self.location.hostname &&
// eslint-disable-next-line no-bitwise
!!~self.location.protocol.indexOf('http');

if (isAnyHostname) {
hostname = self.location.hostname;
}

// `hostname` can be empty when the script path is relative. In that case, specifying
// a protocol would result in an invalid URL.
// When https is used in the app, secure websockets are always necessary
// because the browser doesn't accept non-secure websockets.
if (
hostname &&
(self.location.protocol === 'https:' || urlParts.hostname === '0.0.0.0')
) {
protocol = self.location.protocol;
}

// default values of the sock url if they are not provided
const defaultHost = hostname;
const defaultSockPath = '/sockjs-node';
const defaultPort = urlParts.port;
const defaultPublicPath = '/';

let sockHost = defaultHost;
let sockPath = defaultSockPath;
let sockPort = defaultPort;
let publicPath = defaultPublicPath;

// eslint-disable-next-line no-undefined
const shouldParsePath = path !== null && path !== undefined && path !== '/';
if (shouldParsePath) {
const parsedQuery = querystring.parse(path);
// all of these sock url params are optionally passed in through
// resourceQuery, so we need to fall back to the default if
// they are not provided
sockHost = parsedQuery.sockHost || sockHost;
sockPath = parsedQuery.sockPath || sockPath;
sockPort = parsedQuery.sockPort || sockPort;
publicPath = parsedQuery.publicPath || publicPath;
}
const urlParts = getUrlParts(resourceQuery);

return url.format({
protocol,
auth,
hostname: sockHost,
port: sockPort,
protocol: urlParts.protocol,
auth: urlParts.auth,
hostname: urlParts.sockHost,
port: urlParts.sockPort,
// If sockPath is provided it'll be passed in via the resourceQuery as a
// query param so it has to be parsed out of the querystring in order for the
// client to open the socket to the correct location.
pathname: sockPath,
pathname: urlParts.sockPath,
});
}

Expand Down
93 changes: 93 additions & 0 deletions client-src/default/utils/getUrlParts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import url from 'url';
import querystring from 'querystring';
import getCurrentScriptSource from './getCurrentScriptSource';

function getUrlParts(resourceQuery) {
let urlParts;

if (typeof resourceQuery === 'string' && resourceQuery !== '') {
// If this bundle is inlined, use the resource query to get the correct url.
urlParts = url.parse(resourceQuery.substr(1));
} else {
// Else, get the url from the <script> this file was called with.
const scriptHost = getCurrentScriptSource();

// it seems the reg exp below was intended to cut off the path of a script source,
// so if you have my.host/long/path as the script source, it would become my.host.
// however, it did not work, because if you had http://my.host/long/path it would
// turn it into http:/. Cutting off the path is no longer needed, since we
// simply do url.parse and pull the host from there.

// eslint-disable-next-line no-useless-escape
// scriptHost = scriptHost.replace(/\/[^\/]+$/, '');
urlParts = url.parse(scriptHost || '/', false, true);
}

if (!urlParts.port || urlParts.port === '0') {
urlParts.port = self.location.port;
}

const { auth, query } = urlParts;
let { hostname, protocol } = urlParts;

// check ipv4 and ipv6 `all hostname`
// why do we need this check?
// hostname n/a for file protocol (example, when using electron, ionic)
// see: https://github.com/webpack/webpack-dev-server/pull/384
const isAnyHostname =
(hostname === '0.0.0.0' || hostname === '::') &&
self.location.hostname &&
// eslint-disable-next-line no-bitwise
!!~self.location.protocol.indexOf('http');

if (isAnyHostname) {
hostname = self.location.hostname;
}

// `hostname` can be empty when the script path is relative. In that case, specifying
// a protocol would result in an invalid URL.
// When https is used in the app, secure websockets are always necessary
// because the browser doesn't accept non-secure websockets.
if (
hostname &&
(self.location.protocol === 'https:' || urlParts.hostname === '0.0.0.0')
) {
protocol = self.location.protocol;
}

// default values of the sock url if they are not provided
const defaultHost = hostname;
const defaultSockPath = '/sockjs-node';
const defaultPort = urlParts.port;
const defaultPublicPath = '/';

let sockHost = defaultHost;
let sockPath = defaultSockPath;
let sockPort = defaultPort;
let publicPath = defaultPublicPath;

// eslint-disable-next-line no-undefined
if (query !== null && query !== undefined) {
const parsedQuery = querystring.parse(query);
// all of these sock url params are optionally passed in through
// resourceQuery, so we need to fall back to the default if
// they are not provided
sockHost = parsedQuery.sockHost || sockHost;
sockPath = parsedQuery.sockPath || sockPath;
sockPort = parsedQuery.sockPort || sockPort;
publicPath = parsedQuery.publicPath || publicPath;
}

return {
protocol,
auth,
defaultHost,
defaultPort,
sockHost,
sockPath,
sockPort,
publicPath,
};
}

export default getUrlParts;
8 changes: 3 additions & 5 deletions client-src/default/utils/updatePublicPath.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
'use strict';

/* global __webpack_public_path__ */

const url = require('url');
const getUrlParts = require('./getUrlParts');
import url from 'url';
import getUrlParts from './getUrlParts';

function updatePublicPath(resourceQuery) {
const urlParts = getUrlParts(resourceQuery);
Expand All @@ -26,4 +24,4 @@ function updatePublicPath(resourceQuery) {
__webpack_public_path__ = __webpack_public_path__ || publicPath;
}

module.exports = updatePublicPath;
export default updatePublicPath;
27 changes: 21 additions & 6 deletions lib/utils/addEntries.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,30 @@ function addEntries(config, options, server) {
/** @type {string} */
const domain = createDomain(options, app);
/** @type {string} */
const sockHost = options.clientSocketOptions.host ? `&sockHost=${options.clientSocketOptions.host}` : '';
const sockHost = options.clientSocketOptions.host
? `&sockHost=${encodeURIComponent(options.clientSocketOptions.host)}`
: '';
/** @type {string} */
const sockPath = options.clientSocketOptions.path ? `&sockPath=${options.clientSocketOptions.path}` : '';
const sockPath = options.clientSocketOptions.path
? `&sockPath=${encodeURIComponent(options.clientSocketOptions.path)}`
: '';
/** @type {string} */
const sockPort = options.clientSocketOptions.port ? `&sockPort=${options.clientSocketOptions.port}` : '';
const sockPort = options.clientSocketOptions.port
? `&sockPort=${encodeURIComponent(options.clientSocketOptions.port)}`
: '';
/** @type {string} */
const clientEntry = `${require.resolve(
'../../client/'
)}?${domain}${sockHost}${sockPath}${sockPort}`;
const publicPath = options.publicPath
? `&publicPath=${encodeURIComponent(options.publicPath)}`
: '';

/** @type {string} */
const queryString = `${sockHost}${sockPath}${sockPort}${publicPath}`;

/** @type {string} */
const query = queryString === '' ? '' : `?${queryString.substr(1)}`;

/** @type {string} */
const clientEntry = `${require.resolve('../../client/')}?${domain}${query}`;

/** @type {(string[] | string)} */
let hotEntry;
Expand Down
2 changes: 1 addition & 1 deletion test/cli/cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ describe('CLI', () => {
const { stdout } = await testBin('--sockPath /mysockPath');
expect(
// the /mysockPath becomes %2FmysockPath from encodeURIComponent
/http:\/\/localhost:[0-9]+?sockPath=%2FmysockPath/.test(stdout)
/http:\/\/localhost:[0-9]+\?sockPath=%2FmysockPath/.test(stdout)
).toEqual(true);
});

Expand Down
6 changes: 4 additions & 2 deletions test/client/utils/getUrlParts.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ describe('getUrlParts', () => {
() => () => url
);

// eslint-disable-next-line global-require
const getUrlParts = require('../../../client-src/default/utils/getUrlParts');
const {
default: getUrlParts,
// eslint-disable-next-line global-require
} = require('../../../client-src/default/utils/getUrlParts');

test(`should return url parts when __resourceQuery is ${url}`, () => {
expect(getUrlParts(`?${url}`)).toMatchSnapshot();
Expand Down
6 changes: 4 additions & 2 deletions test/client/utils/updatePublicPath.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ describe('updatePublicPath', () => {
() => () => url
);

// eslint-disable-next-line global-require
const updatePublicPath = require('../../../client-src/default/utils/updatePublicPath');
const {
default: updatePublicPath,
// eslint-disable-next-line global-require
} = require('../../../client-src/default/utils/updatePublicPath');

test(`should set public path when __resourceQuery is ${url}`, () => {
__webpack_public_path__ = '';
Expand Down

0 comments on commit df594ad

Please sign in to comment.