Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BREAKING CHANGES: create static option and remove replaced options #2670

Merged
merged 35 commits into from
Aug 18, 2020
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
972cd03
chore(options): create static option and remove replaced options
knagaitsev Jul 4, 2020
2529175
chore(options): remove contentBase option
knagaitsev Jul 4, 2020
64b767e
chore(cli): rename flags to fit static option
knagaitsev Jul 5, 2020
745fb81
chore(options): add more default handling for static option
knagaitsev Jul 6, 2020
88f08d2
chore(server): remove console log
knagaitsev Jul 7, 2020
e365430
chore(server): rename _watch to watchFiles
knagaitsev Jul 7, 2020
16e0221
test(utils): add more tests and update for normalizeOptions
knagaitsev Jul 23, 2020
497f35d
test(utils): add more normalizeOptions tests
knagaitsev Jul 25, 2020
9fb688c
test(options): update contentBase test to be static directory test
knagaitsev Aug 2, 2020
7728596
test(option): update contentBasePublicPath test to static publicPath
knagaitsev Aug 3, 2020
f1e3302
chore(cli): add static and no-static flags and update createConfig
knagaitsev Aug 3, 2020
963244c
test(options): update validation test
knagaitsev Aug 3, 2020
5df413c
chore(options): allow static to have multiple
knagaitsev Aug 3, 2020
bf0f789
test(options): update options test and change test server helper
knagaitsev Aug 3, 2020
d5a4ae4
test(options): remove use of watchOptions in tests
knagaitsev Aug 3, 2020
d6821c3
test(options): fix some tests using static
knagaitsev Aug 3, 2020
a612b38
chore(options): fix serveIndex to be bool or object
knagaitsev Aug 3, 2020
dfc8f69
chore(options): fix runnable features ordering for api fallback and f…
knagaitsev Aug 3, 2020
da0357f
test(options): fix proxy test and normalizeOptions test
knagaitsev Aug 3, 2020
24c82f6
test(options): disable watching by default for tests and remove conso…
knagaitsev Aug 3, 2020
769e080
test(options): add array static publicPath test
knagaitsev Aug 3, 2020
b64e513
chore(cli): handle multiple static options differently
knagaitsev Aug 4, 2020
888b96e
chore(test): make env variable for chokidar boolean
knagaitsev Aug 4, 2020
544e0b4
test(cli): make cli test use no static flag
knagaitsev Aug 4, 2020
0191a57
test(stats): disable static for stats test
knagaitsev Aug 4, 2020
51c6b2d
test(options): turn off static by default for tests
knagaitsev Aug 4, 2020
1670984
test(options): fix host and port tests
knagaitsev Aug 4, 2020
4b65a57
test(options): only run 1 problematic test
knagaitsev Aug 13, 2020
0e3e20b
test(options): disable watch mode where possible
knagaitsev Aug 13, 2020
f26069f
test(options): fix liveReload test
knagaitsev Aug 13, 2020
ce5468b
chore(server): have only static feature
knagaitsev Aug 14, 2020
efe9bf4
chore(server): add watch to static feature
knagaitsev Aug 14, 2020
b17f327
chore(server): add back multiple runnable features for static
knagaitsev Aug 17, 2020
20f1fb6
chore(server): rename static runnable features
knagaitsev Aug 17, 2020
30b3aca
chore(server): rename static feature methods
knagaitsev Aug 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 3 additions & 14 deletions bin/cli-flags.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ module.exports = {
defaultValue: true,
describe: 'Enables/Disables live reloading on changing files',
},
{
name: 'serveIndex',
type: Boolean,
describe: 'Enables/Disables serveIndex middleware',
defaultValue: true,
},
{
name: 'profile',
type: Boolean,
Expand Down Expand Up @@ -85,16 +79,11 @@ module.exports = {
describe: 'HTTP/2, must be used with HTTPS',
},
{
name: 'content-base',
name: 'static',
type: String,
describe: 'A directory or URL to serve HTML content from.',
group: RESPONSE_GROUP,
},
{
name: 'watch-content-base',
type: Boolean,
describe: 'Enable live-reloading of the content-base.',
describe: 'A directory to serve static content from.',
group: RESPONSE_GROUP,
multiple: true,
},
{
name: 'history-api-fallback',
Expand Down
14 changes: 2 additions & 12 deletions bin/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ const options = {
describe: 'Enables/Disables live reloading on changing files',
default: true,
},
serveIndex: {
type: 'boolean',
describe: 'Enables/Disables serveIndex middleware',
default: true,
},
profile: {
type: 'boolean',
describe: 'Print compilation profile data for progress steps',
Expand Down Expand Up @@ -75,14 +70,9 @@ const options = {
group: SSL_GROUP,
describe: 'HTTP/2, must be used with HTTPS',
},
'content-base': {
static: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be multiple

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evilebottnawi Like --static=example/dir1,example/dir2?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like --static=example/dir1 --static=example/dir2

type: 'string',
describe: 'A directory or URL to serve HTML content from.',
group: RESPONSE_GROUP,
},
'watch-content-base': {
type: 'boolean',
describe: 'Enable live-reloading of the content-base.',
describe: 'A directory to serve static content from.',
group: RESPONSE_GROUP,
},
'history-api-fallback': {
Expand Down
163 changes: 43 additions & 120 deletions lib/Server.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ const webpackDevMiddleware = require('webpack-dev-middleware');
const getFilenameFromUrl = require('webpack-dev-middleware/dist/utils/getFilenameFromUrl')
.default;
const validateOptions = require('schema-utils');
const isAbsoluteUrl = require('is-absolute-url');
const normalizeOptions = require('./utils/normalizeOptions');
const updateCompiler = require('./utils/updateCompiler');
const getCertificate = require('./utils/getCertificate');
Expand Down Expand Up @@ -304,112 +303,43 @@ class Server {
}

setupStaticFeature() {
const contentBase = this.options.contentBase;
const contentBasePublicPath = this.options.contentBasePublicPath;

if (Array.isArray(contentBase)) {
contentBase.forEach((item, index) => {
let publicPath = contentBasePublicPath;

if (
Array.isArray(contentBasePublicPath) &&
contentBasePublicPath[index]
) {
publicPath = contentBasePublicPath[index] || contentBasePublicPath[0];
}

this.app.use(publicPath, express.static(item));
});
} else if (isAbsoluteUrl(String(contentBase))) {
this.logger.warn(
'Using a URL as contentBase is deprecated and will be removed in the next major version. Please use the proxy option instead.'
);

this.logger.warn(
'proxy: {\n\t"*": "<your current contentBase configuration>"\n}'
);

// Redirect every request to contentBase
this.app.get('*', (req, res) => {
res.writeHead(302, {
Location: contentBase + req.path + (req._parsedUrl.search || ''),
});

res.end();
});
} else if (typeof contentBase === 'number') {
this.logger.warn(
'Using a number as contentBase is deprecated and will be removed in the next major version. Please use the proxy option instead.'
);

this.logger.warn(
'proxy: {\n\t"*": "//localhost:<your current contentBase configuration>"\n}'
);

// Redirect every request to the port contentBase
this.app.get('*', (req, res) => {
res.writeHead(302, {
Location: `//localhost:${contentBase}${req.path}${
req._parsedUrl.search || ''
}`,
});

res.end();
this.options.static.forEach((staticOption) => {
staticOption.publicPath.forEach((publicPath) => {
this.app.use(
publicPath,
express.static(staticOption.directory, staticOption.staticOptions)
);
});
} else {
// route content request
this.app.use(
contentBasePublicPath,
express.static(contentBase, this.options.staticOptions)
);
}
});
}

setupServeIndexFeature() {
const contentBase = this.options.contentBase;
const contentBasePublicPath = this.options.contentBasePublicPath;

if (Array.isArray(contentBase)) {
contentBase.forEach((item) => {
this.app.use(contentBasePublicPath, (req, res, next) => {
// serve-index doesn't fallthrough non-get/head request to next middleware
if (req.method !== 'GET' && req.method !== 'HEAD') {
return next();
}
this.options.static.forEach((staticOption) => {
staticOption.publicPath.forEach((publicPath) => {
if (staticOption.serveIndex) {
this.app.use(publicPath, (req, res, next) => {
// serve-index doesn't fallthrough non-get/head request to next middleware
if (req.method !== 'GET' && req.method !== 'HEAD') {
return next();
}

serveIndex(item, { icons: true })(req, res, next);
});
});
} else if (
typeof contentBase !== 'number' &&
!isAbsoluteUrl(String(contentBase))
) {
this.app.use(contentBasePublicPath, (req, res, next) => {
// serve-index doesn't fallthrough non-get/head request to next middleware
if (req.method !== 'GET' && req.method !== 'HEAD') {
return next();
serveIndex(staticOption.directory, staticOption.serveIndex)(
req,
res,
next
);
});
}

serveIndex(contentBase, { icons: true })(req, res, next);
});
}
});
}

setupWatchStaticFeature() {
const contentBase = this.options.contentBase;

if (isAbsoluteUrl(String(contentBase)) || typeof contentBase === 'number') {
throw new Error('Watching remote files is not supported.');
} else if (Array.isArray(contentBase)) {
contentBase.forEach((item) => {
if (isAbsoluteUrl(String(item)) || typeof item === 'number') {
throw new Error('Watching remote files is not supported.');
}
this._watch(item);
});
} else {
this._watch(contentBase);
}
this.options.static.forEach((staticOption) => {
if (staticOption.watch) {
this.watchFiles(staticOption.directory, staticOption.watch);
}
});
}

setupOnBeforeSetupMiddlewareFeature() {
Expand Down Expand Up @@ -449,16 +379,13 @@ class Server {
this.setupHistoryApiFallbackFeature();
}
},
// Todo rename to `static` in future major release
contentBaseFiles: () => {
static: () => {
this.setupStaticFeature();
},
// Todo rename to `serveIndex` in future major release
contentBaseIndex: () => {
staticServeIndex: () => {
this.setupServeIndexFeature();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And let's rename method names: this.setupStaticServeIndexFeature, as I written above 🥇

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And let's rename method names: this.setupStaticServeIndexFeature, as I written above

Just did that 👍

},
// Todo rename to `watchStatic` in future major release
watchContentBase: () => {
staticWatch: () => {
this.setupWatchStaticFeature();
},
onBeforeSetupMiddleware: () => {
Expand Down Expand Up @@ -501,24 +428,20 @@ class Server {
runnableFeatures.push('proxy', 'middleware');
}

if (this.options.contentBase !== false) {
runnableFeatures.push('contentBaseFiles');
if (this.options.static) {
runnableFeatures.push('static');
}

if (this.options.historyApiFallback) {
runnableFeatures.push('historyApiFallback', 'middleware');

if (this.options.contentBase !== false) {
runnableFeatures.push('contentBaseFiles');
if (this.options.static) {
runnableFeatures.push('static');
}
}

if (this.options.contentBase && this.options.serveIndex) {
runnableFeatures.push('contentBaseIndex');
}

if (this.options.watchContentBase) {
runnableFeatures.push('watchContentBase');
if (this.options.static) {
runnableFeatures.push('staticServeIndex', 'staticWatch');
}

runnableFeatures.push('magicHtml');
Expand Down Expand Up @@ -903,31 +826,31 @@ class Server {
}
}

_watch(watchPath) {
watchFiles(watchPath, watchOptions) {
// duplicate the same massaging of options that watchpack performs
// https://github.com/webpack/watchpack/blob/master/lib/DirectoryWatcher.js#L49
// this isn't an elegant solution, but we'll improve it in the future
// eslint-disable-next-line no-undefined
const usePolling = this.options.watchOptions.poll ? true : undefined;
const usePolling = watchOptions.poll ? true : undefined;
const interval =
typeof this.options.watchOptions.poll === 'number'
? this.options.watchOptions.poll
typeof watchOptions.poll === 'number'
? watchOptions.poll
: // eslint-disable-next-line no-undefined
undefined;

const watchOptions = {
const finalWatchOptions = {
ignoreInitial: true,
persistent: true,
followSymlinks: false,
atomic: false,
alwaysStat: true,
ignorePermissionErrors: true,
ignored: this.options.watchOptions.ignored,
ignored: watchOptions.ignored,
usePolling,
interval,
};

const watcher = chokidar.watch(watchPath, watchOptions);
const watcher = chokidar.watch(watchPath, finalWatchOptions);
// disabling refreshing on changing the content
if (this.options.liveReload) {
watcher.on('change', () => {
Expand Down
Loading