Commit a61be9c6 authored by Joe Haddad's avatar Joe Haddad Committed by Dan Abramov
Browse files

Add module scope plugin (#2189)

* Add module scope plugin

* Oops

* Add comments

* Check windows seps too

* More descriptive error

* Document it
parent e1f22b59
3 merge requests!12191Lim.Pisey.168:/Identified - We are currently investigating reports of missing build logs. The issue has been identified and a resolution is in progress. We will provide a further update when available.Mar 21, 09:02 UTC,!12853brikk,!5717Automatically extract project file structure from build bundle file
Showing with 107 additions and 0 deletions
+107 -0
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
const chalk = require('chalk');
const path = require('path');
class ModuleScopePlugin {
constructor(appSrc) {
this.appSrc = appSrc;
}
apply(resolver) {
const { appSrc } = this;
resolver.plugin('file', (request, callback) => {
// Unknown issuer, probably webpack internals
if (!request.context.issuer) {
return callback();
}
if (
// If this resolves to a node_module, we don't care what happens next
request.descriptionFileRoot.indexOf('/node_modules/') !== -1 ||
request.descriptionFileRoot.indexOf('\\node_modules\\') !== -1 ||
// Make sure this request was manual
!request.__innerRequest_request
) {
return callback();
}
// Resolve the issuer from our appSrc and make sure it's one of our files
// Maybe an indexOf === 0 would be better?
const relative = path.relative(appSrc, request.context.issuer);
// If it's not in src/ or a subdirectory, not our request!
if (relative[0] === '.') {
return callback();
}
// Find path from src to the requested file
const requestRelative = path.relative(
appSrc,
path.resolve(
path.dirname(request.context.issuer),
request.__innerRequest_request
)
);
// Error if in a parent directory of src/
if (requestRelative[0] === '.') {
callback(
new Error(
`You attempted to import ${chalk.cyan(request.__innerRequest_request)} which falls outside of the project ${chalk.cyan('src/')} directory. ` +
`Relative imports outside of ${chalk.cyan('src/')} are not supported. ` +
`You can either move it inside ${chalk.cyan('src/')}, or add a symlink to it from project's ${chalk.cyan('node_modules/')}.`
),
request
);
} else {
callback();
}
});
}
}
module.exports = ModuleScopePlugin;
......@@ -56,6 +56,26 @@ module.exports = {
}
```
#### `new ModuleScopePlugin(appSrc: string)`
This Webpack plugin ensures that relative imports from app's source directory don't reach outside of it.
```js
var path = require('path');
var ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
module.exports = {
// ...
plugins: [
new ModuleScopePlugin(paths.appSrc),
// ...
],
// ...
}
```
#### `new WatchMissingNodeModulesPlugin(nodeModulesPath: string)`
This Webpack plugin ensures `npm install <library>` forces a project rebuild.<br>
......
......@@ -21,6 +21,7 @@
"getProcessForPort.js",
"InterpolateHtmlPlugin.js",
"launchEditor.js",
"ModuleScopePlugin.js",
"openBrowser.js",
"openChrome.applescript",
"prepareProxy.js",
......
......@@ -18,6 +18,7 @@ const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const eslintFormatter = require('react-dev-utils/eslintFormatter');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getClientEnvironment = require('./env');
const paths = require('./paths');
......@@ -106,6 +107,14 @@ module.exports = {
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
},
plugins: [
// Prevents users from importing files from outside of src/ (or node_modules/).
// This often causes confusion because we only process files within src/ with babel.
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
// please link the files into your node_modules/ and let module-resolution kick in.
// Make sure your source files are compiled, as they will not be processed in any way.
new ModuleScopePlugin(paths.appSrc),
],
},
module: {
strictExportPresence: true,
......
......@@ -18,6 +18,7 @@ const ExtractTextPlugin = require('extract-text-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const eslintFormatter = require('react-dev-utils/eslintFormatter');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const paths = require('./paths');
const getClientEnvironment = require('./env');
......@@ -103,6 +104,14 @@ module.exports = {
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
},
plugins: [
// Prevents users from importing files from outside of src/ (or node_modules/).
// This often causes confusion because we only process files within src/ with babel.
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
// please link the files into your node_modules/ and let module-resolution kick in.
// Make sure your source files are compiled, as they will not be processed in any way.
new ModuleScopePlugin(paths.appSrc),
],
},
module: {
strictExportPresence: true,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment