-
-
Notifications
You must be signed in to change notification settings - Fork 26.9k
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
Plugin system #2756
Plugin system #2756
Conversation
Glad you asked! Plugins exist as packages prefixed by
Any mutations must be applied using helpers exported by
These mutations are applied to our dev and prod webpack configuration files at runtime while not ejected: module.exports = applyPlugins(base, ['typescript'], { paths }); When ejecting, these mutations must happen to the configuration files pre-emit. To achieve this, the plugins are parsed and placed into the configuration file to remove the seams. 😄 tl;dr Magic! ✨ 🔮 |
/cc @viankakrisna who was interested in seeing this prototype |
I'm hoping this would eventually enable server-side rendering 😄 |
Missing installing plugin dependencies, but you get the idea: $ cd app1/
$ echo y | yarn eject
$ git add -A; git commit -m "normal"
$ cd ../app2/
$ yarn add react-scripts-plugin-typescript # All that's required to add typescript support, pre and post eject
$ echo y | yarn eject
$ cp -r . ../app1/
$ cd ../app1/
$ git diff | pbcopy diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js
index eaabb8a..42ea5e7 100644
--- a/config/webpack.config.dev.js
+++ b/config/webpack.config.dev.js
@@ -84,7 +84,7 @@ module.exports = {
// https://github.com/facebookincubator/create-react-app/issues/290
// `web` extension prefixes have been added for better support
// for React Native Web.
- extensions: ['.web.js', '.js', '.json', '.web.jsx', '.jsx'],
+ extensions: ['.web.js', '.js', '.tsx', '.ts', '.json', '.web.jsx', '.jsx'],
alias: {
// Support React Native Web
@@ -153,6 +153,15 @@ module.exports = {
cacheDirectory: true,
},
},
+ {
+ // Process TypeScript with `at-loader`
+ test: /\.(ts|tsx)$/,
+ include: paths.appSrc,
+ loader: require.resolve('awesome-typescript-loader'),
+ options: {
+ silent: true,
+ },
+ },
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// "style" loader turns CSS into JS modules that inject <style> tags.
diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js
index 7d4649e..fe0ef64 100644
--- a/config/webpack.config.prod.js
+++ b/config/webpack.config.prod.js
@@ -86,7 +86,7 @@ module.exports = {
// https://github.com/facebookincubator/create-react-app/issues/290
// `web` extension prefixes have been added for better support
// for React Native Web.
- extensions: ['.web.js', '.js', '.json', '.web.jsx', '.jsx'],
+ extensions: ['.web.js', '.js', '.tsx', '.ts', '.json', '.web.jsx', '.jsx'],
alias: {
// Support React Native Web
@@ -151,6 +151,15 @@ module.exports = {
compact: true,
},
},
+ {
+ // Process TypeScript with `at-loader`
+ test: /\.(ts|tsx)$/,
+ include: paths.appSrc,
+ loader: require.resolve('awesome-typescript-loader'),
+ options: {
+ silent: true,
+ },
+ },
// The notation here is somewhat confusing.
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
diff --git a/package.json b/package.json
index 1239483..4ba74fc 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "name": "app1",
+ "name": "app2",
"version": "0.1.0",
"private": true,
"dependencies": { Off to bed now, night! |
try { | ||
return require.resolve(`react-scripts-plugin-${p}`); | ||
} catch (e) { | ||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any expected errors that can happen here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plugin installation is optional, so require.resolve
throws an error if the package is missing.
Nice! it's like neutrino presets, but ejectable. :D Maybe on the next iteration, we can detect if the user is importing Another thing is where the plugins repo would live? Can we maintain a list of the blessed react-scripts plugins? If not, what's stopping people to writing plugin that expose overriding all react-scripts configuration? It's really exciting! |
(and frightening at the same time) |
Hi, sorry if this suggestion is silly or what I'm saying is unclear - I'm still a fairly junior developer. But here's my two cents: Personally I don't like the idea of adding/removing plugins mutating the global webpack configuration. It opens users up to all sorts of permanent errors - all it takes is one buggy plugin to corrupt things permanently. What about having plugins just insert a single file into a I see this as working in a similar way to how Jekyll loads plugins, by simply running every file in the |
@Arrow7000 that's why I think it's frightening, but if CRA maintainer can control the plugin code, and maintain a whitelist of allowed plugins, they can curate the experience and provide bug fixes early. |
@viankakrisna yes curation will help prevent the problem, but if webpack configs are being mutated then one bug in a plugin can ruin your config, regardless of any subsequent bug fixes to the plugin. |
Then we need to write test of the playability of each plugin that we have. And maybe detect if the plugin version needs to be updated? that's why the core should have a list of installable plugins (and it's compatible version) |
Plugins will live within the monorepo; for now (and probably indefinitely) plugins are whitelisted so people cannot create their own.
Yeah, testability is key here. Playability is a worry as we upgrade |
The plugins will never actually mutate the file unless you are ejecting, so there is no potential for permanent errors. This impl is contingent on updating remaining as simple as it is now.
Like above, installing the plugins themselves and uninstalling will not actually cause any true mutations -- mutation only happens when ejecting and is intended to be permanent.
Thanks for chiming in and I wish I was a little more clear off the bat! |
Perhaps! Maybe you could contribute support if a system like this was put into place. |
If we could extend plugins to implement @decerators it would've saved our team some huge headaches when implementing MobX. This feature has our 👍 |
@nsarafa
Unfortunately, we will not allow the creation of custom plugins (or at least not yet). We have no plans of enabling decorators (or any proposal/language feature for that matter) until they reach stage-3 and become commonplace. Sorry! |
Proposal now installs plugin dependencies during eject. Next step is to automate |
I'd love some review, feedback, or suggestions! |
Closing this in favor of #2784. |
I'd like to preface this by stating that it is very likely a system like this may never be added to
create-react-app
, and is simply being showcased to create discussion around the feasibility of such an idea.A plugin system is something which proposes to solve many problems.
For instance, we'd like to be able to add support for things like Relay, without increasing the initial installation size of the build tooling.
This could also potentially be applied to things like TypeScript, Sass, et al.
Design goals:
yarn add react-scripts-plugin-relay
)Design constraints:
This PR introduces a POC plugin system with initial support for TypeScript.
TODO
tsconfig.json
], etc)