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

Implement the no-use-before-define ESLint rule #770

Merged
merged 4 commits into from
Nov 28, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
2 changes: 1 addition & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
"no-unreachable": 2,
"no-unused-expressions": 0,
"no-unused-vars": 2,
"no-use-before-define": 0,
"no-use-before-define": ["error", { "functions": false }],
"no-wrap-func": 0,
"quotes": [
0,
Expand Down
194 changes: 97 additions & 97 deletions packages/react-server-cli/src/compileClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,93 +13,6 @@ import callerDependency from "./callerDependency"
// import {logging} from "react-server"
// const logger = logging.getLogger(__LOGGER__);

// compiles the routes file for browser clients using webpack.
// returns a tuple of { compiler, serverRoutes }. compiler is a webpack compiler
// that is ready to have run called, and serverRoutes is a promise that resolve to
// a path to the transpiled server routes file path. The promise only resolves
// once the compiler has been run. The file path returned from the promise
// can be required and passed in to reactServer.middleware().
// TODO: add options for sourcemaps.
export default (opts = {}) => {
const {
routes,
workingDir = "./__clientTemp",
routesDir = ".",
outputDir = workingDir + "/build",
outputUrl = "/static/",
hot = true,
minify = false,
stats = false,
longTermCaching = false,
} = opts;
if (longTermCaching && hot) {
// chunk hashes can't be used in hot mode, so we can't use long-term caching
// and hot mode at the same time.
throw new Error("Hot reload cannot be used with long-term caching. Please disable either long-term caching or hot reload.");
}

var webpackConfigFunc = (data) => { return data }
if (opts['webpack-config']) {
const webpackDirAbsolute = path.resolve(process.cwd(), opts['webpack-config']);
const userWebpackConfigFunc = require(webpackDirAbsolute)
webpackConfigFunc = userWebpackConfigFunc.default
}

const workingDirAbsolute = path.resolve(process.cwd(), workingDir);
mkdirp.sync(workingDirAbsolute);
const outputDirAbsolute = path.resolve(process.cwd(), outputDir);
mkdirp.sync(outputDirAbsolute);

const routesDirAbsolute = path.resolve(process.cwd(), routesDir);

// for each route, let's create an entrypoint file that includes the page file and the routes file
let bootstrapFile = writeClientBootstrapFile(workingDirAbsolute, opts);
const entrypointBase = hot ? [
require.resolve("webpack-dev-server/client") + "?" + outputUrl,
require.resolve("webpack/hot/only-dev-server"),
] : [];
let entrypoints = {};
for (let routeName of Object.keys(routes.routes)) {
let route = routes.routes[routeName];
let formats = normalizeRoutesPage(route.page);
for (let format of Object.keys(formats)) {
const absolutePathToPage = require.resolve(path.resolve(routesDirAbsolute, formats[format]));

entrypoints[`${routeName}${format !== "default" ? "-" + format : ""}`] = [
...entrypointBase,
bootstrapFile,
absolutePathToPage,
];
}
}

// now rewrite the routes file out in a webpack-compatible way.
writeWebpackCompatibleRoutesFile(routes, routesDir, workingDirAbsolute, null, true);

// finally, let's pack this up with webpack.
const compiler = webpack(webpackConfigFunc(packageCodeForBrowser(entrypoints, outputDirAbsolute, outputUrl, hot, minify, longTermCaching, stats)));

const serverRoutes = new Promise((resolve) => {
compiler.plugin("done", (stats) => {
const manifest = statsToManifest(stats);
fs.writeFileSync(path.join(outputDir, "manifest.json"), JSON.stringify(manifest));

// this file is generated by the build in non-hot mode, but we don't need
// it (we got the data ourselves from stats in statsToManifest()).
if (!hot) {
fs.unlinkSync(path.join(outputDir, "chunk-manifest.json"));
}

resolve(writeWebpackCompatibleRoutesFile(routes, routesDir, workingDirAbsolute, outputUrl, false, manifest));
});
});

return {
serverRoutes,
compiler,
};
}

// takes in the stats object from a successful compilation and returns a manifest
// object that characterizes the results of the compilation for CSS/JS loading
// and integrity checking. the manifest has the following entries:
Expand Down Expand Up @@ -251,6 +164,16 @@ const packageCodeForBrowser = (entrypoints, outputDir, outputUrl, hot, minify, l
return webpackConfig;
};

// the page value for routes.routes["SomeRoute"] can either be a string for the default
// module name or an object mapping format names to module names. This method normalizes
// the value to an object.
const normalizeRoutesPage = (page) => {
if (typeof page === "string") {
return {default: page};
}
return page;
}

// writes out a routes file that can be used at runtime.
const writeWebpackCompatibleRoutesFile = (routes, routesDir, workingDirAbsolute, staticUrl, isClient, manifest) => {
let routesOutput = [];
Expand Down Expand Up @@ -331,16 +254,6 @@ module.exports = {
};


// the page value for routes.routes["SomeRoute"] can either be a string for the default
// module name or an object mapping format names to module names. This method normalizes
// the value to an object.
const normalizeRoutesPage = (page) => {
if (typeof page === "string") {
return {default: page};
}
return page;
}

// writes out a bootstrap file for the client which in turn includes the client
// routes file. note that outputDir must be the same directory as the client routes
// file, which must be named "routes_client".
Expand All @@ -367,3 +280,90 @@ const writeClientBootstrapFile = (outputDir, opts) => {
);
return outputFile;
};

// compiles the routes file for browser clients using webpack.
// returns a tuple of { compiler, serverRoutes }. compiler is a webpack compiler
// that is ready to have run called, and serverRoutes is a promise that resolve to
// a path to the transpiled server routes file path. The promise only resolves
// once the compiler has been run. The file path returned from the promise
// can be required and passed in to reactServer.middleware().
// TODO: add options for sourcemaps.
export default (opts = {}) => {
const {
routes,
workingDir = "./__clientTemp",
routesDir = ".",
outputDir = workingDir + "/build",
outputUrl = "/static/",
hot = true,
minify = false,
stats = false,
longTermCaching = false,
} = opts;
if (longTermCaching && hot) {
// chunk hashes can't be used in hot mode, so we can't use long-term caching
// and hot mode at the same time.
throw new Error("Hot reload cannot be used with long-term caching. Please disable either long-term caching or hot reload.");
}

var webpackConfigFunc = (data) => { return data }
if (opts['webpack-config']) {
const webpackDirAbsolute = path.resolve(process.cwd(), opts['webpack-config']);
const userWebpackConfigFunc = require(webpackDirAbsolute)
webpackConfigFunc = userWebpackConfigFunc.default
}

const workingDirAbsolute = path.resolve(process.cwd(), workingDir);
mkdirp.sync(workingDirAbsolute);
const outputDirAbsolute = path.resolve(process.cwd(), outputDir);
mkdirp.sync(outputDirAbsolute);

const routesDirAbsolute = path.resolve(process.cwd(), routesDir);

// for each route, let's create an entrypoint file that includes the page file and the routes file
let bootstrapFile = writeClientBootstrapFile(workingDirAbsolute, opts);
const entrypointBase = hot ? [
require.resolve("webpack-dev-server/client") + "?" + outputUrl,
require.resolve("webpack/hot/only-dev-server"),
] : [];
let entrypoints = {};
for (let routeName of Object.keys(routes.routes)) {
let route = routes.routes[routeName];
let formats = normalizeRoutesPage(route.page);
for (let format of Object.keys(formats)) {
const absolutePathToPage = require.resolve(path.resolve(routesDirAbsolute, formats[format]));

entrypoints[`${routeName}${format !== "default" ? "-" + format : ""}`] = [
...entrypointBase,
bootstrapFile,
absolutePathToPage,
];
}
}

// now rewrite the routes file out in a webpack-compatible way.
writeWebpackCompatibleRoutesFile(routes, routesDir, workingDirAbsolute, null, true);

// finally, let's pack this up with webpack.
const compiler = webpack(webpackConfigFunc(packageCodeForBrowser(entrypoints, outputDirAbsolute, outputUrl, hot, minify, longTermCaching, stats)));

const serverRoutes = new Promise((resolve) => {
compiler.plugin("done", (stats) => {
const manifest = statsToManifest(stats);
fs.writeFileSync(path.join(outputDir, "manifest.json"), JSON.stringify(manifest));

// this file is generated by the build in non-hot mode, but we don't need
// it (we got the data ourselves from stats in statsToManifest()).
if (!hot) {
fs.unlinkSync(path.join(outputDir, "chunk-manifest.json"));
}

resolve(writeWebpackCompatibleRoutesFile(routes, routesDir, workingDirAbsolute, outputUrl, false, manifest));
});
});

return {
serverRoutes,
compiler,
};
}
106 changes: 53 additions & 53 deletions packages/react-server-cli/src/parseCliArgs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,59 @@ import yargs from "yargs"
import fs from "fs"
import pem from "pem"

const sslize = async argv => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this is set up with {functions: false}, would it work to just turn these into normal functions to avoid having to move them above the default exports?

Like, could this stay where it was and turn into:

async function sslize(argv) {
    ...
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, heh, you had the same thought. 😁


const {
https,
httpsKey,
httpsCert,
httpsCa,
httpsPfx,
httpsPassphrase,
} = argv;

if (https || (httpsKey && httpsCert) || httpsPfx) {
if ((httpsKey && httpsCert) || httpsPfx) {
argv.httpsOptions = {
key: httpsKey ? fs.readFileSync(httpsKey) : undefined,
cert: httpsCert ? fs.readFileSync(httpsCert) : undefined,
ca: httpsCa ? fs.readFileSync(httpsCa) : undefined,
pfx: httpsPfx ? fs.readFileSync(httpsPfx) : undefined,
passphrase: httpsPassphrase,
};
} else {
argv.httpsOptions = await new Promise((resolve, reject) => {
pem.createCertificate({ days: 1, selfSigned: true }, (err, keys) => {
if (err) {
reject(err);
}
resolve({ key: keys.serviceKey, cert: keys.certificate });
});
});
}
} else {
argv.httpsOptions = false;
}

if ((httpsKey || httpsCert || httpsCa) && httpsPfx) {
throw new Error("If you set https.pfx, you can't set https.key, https.cert, or https.ca.");
}

return argv;
}

const removeUndefinedValues = (input) => {
const result = Object.assign({}, input);

for (let key of Object.keys(input)) {
if (result[key] === undefined) {
delete result[key];
}
}

return result;
}

export default (args = process.argv) => {
var argsDefinition = yargs(args)
.usage('Usage: $0 <command> [options]')
Expand Down Expand Up @@ -134,56 +187,3 @@ export default (args = process.argv) => {
return sslize(removeUndefinedValues(parsedArgs));

}

const sslize = async argv => {

const {
https,
httpsKey,
httpsCert,
httpsCa,
httpsPfx,
httpsPassphrase,
} = argv;

if (https || (httpsKey && httpsCert) || httpsPfx) {
if ((httpsKey && httpsCert) || httpsPfx) {
argv.httpsOptions = {
key: httpsKey ? fs.readFileSync(httpsKey) : undefined,
cert: httpsCert ? fs.readFileSync(httpsCert) : undefined,
ca: httpsCa ? fs.readFileSync(httpsCa) : undefined,
pfx: httpsPfx ? fs.readFileSync(httpsPfx) : undefined,
passphrase: httpsPassphrase,
};
} else {
argv.httpsOptions = await new Promise((resolve, reject) => {
pem.createCertificate({ days: 1, selfSigned: true }, (err, keys) => {
if (err) {
reject(err);
}
resolve({ key: keys.serviceKey, cert: keys.certificate });
});
});
}
} else {
argv.httpsOptions = false;
}

if ((httpsKey || httpsCert || httpsCa) && httpsPfx) {
throw new Error("If you set https.pfx, you can't set https.key, https.cert, or https.ca.");
}

return argv;
}

const removeUndefinedValues = (input) => {
const result = Object.assign({}, input);

for (let key of Object.keys(input)) {
if (result[key] === undefined) {
delete result[key];
}
}

return result;
}
6 changes: 3 additions & 3 deletions packages/react-server-website/components/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ const links = [
},
]

const currentPath = () => getCurrentRequestContext().getCurrentPath();
const classIfActive = (path, internal) => (path.split("/")[1] === currentPath().split("/")[1]) && internal ? {className:"active"}:{}

const HeaderLink = ({label, path, internal}) => {
// Internal links use Client Transitions for faster load times.
if (internal) {
Expand All @@ -51,9 +54,6 @@ class MenuControl extends React.Component {
}
}

const currentPath = () => getCurrentRequestContext().getCurrentPath();
const classIfActive = (path, internal) => (path.split("/")[1] === currentPath().split("/")[1]) && internal ? {className:"active"}:{}


export default class Header extends React.Component {
constructor(props) {
Expand Down
20 changes: 10 additions & 10 deletions packages/react-server-website/components/doc-contents.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,24 @@ import SvgDropdown from './assets/SvgDropdown';

import './doc-contents.less'

const ContentsSection = ({name, pages}) => (
<div className='contentsSection'>
<h3>{name}</h3>
<ul>{pages.map(ContentsLink)}</ul>
</div>
)

const currentPath = () => getCurrentRequestContext().getCurrentPath();

const classIfActive = path => (path === currentPath())?{className:"active"}:{}

const ContentsLinkWithMungedPath = (name, path) => <li {...classIfActive(path)}>
<Link reuseDom bundleData path={path}>{name}</Link>
</li>

const ContentsLink = ({name, path}) => ContentsLinkWithMungedPath(
name, join("/docs", path)
)

const ContentsLinkWithMungedPath = (name, path) => <li {...classIfActive(path)}>
<Link reuseDom bundleData path={path}>{name}</Link>
</li>
const ContentsSection = ({name, pages}) => (
<div className='contentsSection'>
<h3>{name}</h3>
<ul>{pages.map(ContentsLink)}</ul>
</div>
)

export default class DocContents extends React.Component {
constructor(props) {
Expand Down
Loading