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

[RFC] Plugins #9133

Open
timneutkens opened this issue Oct 18, 2019 · 58 comments
Open

[RFC] Plugins #9133

timneutkens opened this issue Oct 18, 2019 · 58 comments
Assignees
Labels
RFC

Comments

@timneutkens
Copy link
Member

@timneutkens timneutkens commented Oct 18, 2019

Authored together with @ijjk.

Goals

  • Provide an official plugin system for Next.js
  • Allow hooking into different parts of the Next.js lifecycle
  • Provide the right limits for plugins to prevent them from de-optimizing applications
  • Warn users when a plugin is being inefficient
  • Provide a zero-config approach to plugins
  • Provide code splitting for plugins

Background

Over time the Next.js examples directory has grown to 210+ examples. These examples show how to integrate external libraries for styling, error reporting, data fetching, and many other applications.

Most of these examples require a bit of configuration in various parts of Next.js, for example, in _document, _app, or pages. And sometimes the implementation details have to match exactly the example otherwise the library behaves in a different way. We've seen this for the example with material-ui that has a flash of unstyled content if _document is not implemented.

There are also examples that are using getInitialProps where it's not always needed, one of the examples of this is the redux example. It currently requires having getInitialProps which causes all pages to opt-out of automatic static rendering.

To solve these issues and provide an overall better developer experience we intend to introduce a plugin system.

Plugins will be able to hook into specific lifecycle parts of Next.js.

For example, to execute a specific bit of code after hydration happens or to inject a script like Google Analytics into the body of every page.

The main goal for the plugin system will be to make you more productive while preserving the Next.js production performance characteristics.

One way we're trying to achieve this is that attached lifecycle methods are automatically code-split in a similar fashion as pages.

This new plugins system will provide you with the best developer experience when integrating libraries and we're excited to see the new ways of integrating and extending Next.js' functionality this system will enable.

Proposal

To provide a seamless plugin experience, Next.js will add built-in support for auto-detecting packages with the naming convention @next/plugin-, next-plugin-, or @<scope>/next-plugin-. We will also investigate allowing local plugins in a plugins or next-plugins directory that don't require being installed.

Each of these plugins will have a meta field named nextjs in their package.json that gives us some extra information about the plugin like the required env values it relies on.

// @next/plugin-google-analytics#package.json
{
  "name": "@next/plugin-google-analytics",
  "version": "9.1.2-canary.1",
  "nextjs": {
    "name": "Google Analytics",
    "required-env": ["GA_TRACKING_ID"]
  },
  "peerDependencies": {
    "next": "*"
  }
}

The only other required step for a plugin is to have a src directory with the lifecycle methods it wants to hook into.

To start, we explored what it would take to create a Google Analytics plugin and a Sentry plugin. Creating these example plugins gave us insight into the lifecycle methods that were needed.

Currently exposed lifecycle methods

The naming scheme for lifecycle methods will be based on:

name + '-' + context

name will be based on the lifecycle, potentially prefixed by on if it's an event.

The context will be client, server or build. It's appended at the end of the file name so that if a lifecycle is available on both client and server it will be sorted together in editors.

Some of the initial methods that come to mind:

// on-init-client.js
export default async function onInitClient({ router }): void {
  // called on client init, before hydration
}
// on-error-client.js
export default async function onErrorClient({ err }): void {
  // called when an error occurs during render on the client
}
// on-error-server.js
export default async function onErrorServer({ err }): void {
  // called when an error occurs during render on the server
}
// document-head-tags-server.js
export default function headTags(DocumentCtx): Promise<ReactElement[]> {
  // called when rendering the initial document, allows adding tags to the head
  return (
    <>
      <script src="googleanalytics.com/code.js" async />
    </>
  );
}
// document-body-tags-server.js
export default async function bodyTags(DocumentCtx): Promise<ReactElement[]> {
  // called when rendering the initial document, allows adding tags to the body
  return (
    <>
      <script src="example.com/body.js" async />
    </>
  );
}
// babel-preset-build.js
module.exports = function babelPreset({ plugins, presets }, config): {
  // Babel config that will be merged inside next/babel
}

An example folder structure for one of these plugins would look like this

package.json
src/
  on-error-client.js
  on-error-server.js
  on-init-client.js
  on-init-server.js

Following this structure allows Next.js to provide a zero-config experience for plugins. Not only that, but it also allows us to code split these methods efficiently, only loading the parts of a plugin that are necessary at a specific point. We can also detect which parts of a plugin are being less efficient since they are all their own file and warn users of this.

Providing information to plugins

Although we aim to make adding plugins to a project as simple as possible, some plugins still require some information like a token or an id.

To handle this, we allow you to provide these values using the current env config in next.config.js and the values will be injected into the plugin where needed during build time.

// next.config.js
module.exports = {
  env: {
    GA_TRACKING_ID: "myTrackingId"
  }
};

If a value listed in a plugin's required-env is missing in your next.config.js's env we will error and require you provide these values so that the plugin is able to function correctly. We may need to investigate name spacing these values to prevent collision between plugins.

@Janpot

This comment has been minimized.

Copy link
Contributor

@Janpot Janpot commented Oct 18, 2019

Interesting concept. In case you haven't seen it yet, here's an interesting read about some considerations around plugin systems that I think apply here as well. How would you handle ordering and plugins depending on each other, and with that, deduplication?

@flybayer

This comment has been minimized.

Copy link
Contributor

@flybayer flybayer commented Oct 18, 2019

This'll be awesome!

We also need ability to modify the webpack config, for example to make next-plugin-react-native-web.

Perhaps plugins can use the exact same next.config.js format for adding any modifications needed there (including things like assetPrefix).

@franklinjavier

This comment has been minimized.

Copy link

@franklinjavier franklinjavier commented Oct 18, 2019

Love it 👊

@flybayer

This comment has been minimized.

Copy link
Contributor

@flybayer flybayer commented Oct 18, 2019

What I need for next-plugin-webextenson

Context: I am using Next.js to power a Chrome/Firefox extension

I'm currently using a custom server during development to:

  1. Write each page's html to disk on (a) server start and (b) page change
  2. Copy all files in public to the same directory as the above pages

Here's what I need:

  1. A hook into app.renderToHTML() that provides me with req, res, and output html
    • I'll use this to write that html to disk
  2. A hook that provides me all the pages along with app
    • I'll use this on startup to call app.renderToHTML() for each page
    • This is essential because I can't wait for a client to request a page.
  3. A hook on startup so I can copy all files in public to the same place as the page html files

UPDATE:

The absolute minimum I need is:

  1. A development-only hook into app.renderToHTML() that provides me with req, res, and output html
    • I'll use this to write that html to disk
  2. A development-only hook after server boot that provides app
    • I'll use this to do everything else I need like copy certain files, etc.
@Jarred-Sumner

This comment has been minimized.

Copy link

@Jarred-Sumner Jarred-Sumner commented Oct 18, 2019

This looks really cool!

If a value listed in a plugin's required-env is missing in your next.config.js's env we will error and require you provide these values so that the plugin is able to function correctly.

I could see erroring when missing env vars being a source of frustration — sometimes, when working quickly, you install some packages but don’t end up using them. The next time the developer restarts their server in development, it would error.

Perhaps instead, it could warn in development when the server first loads, skip loading the plugin, and then error during the production build? With a message that says to either provide the missing env vars or uninstall the plugin (with the package name, and ideally, a command to copy paste to uninstall)

Ideally, plugins would be able to optionally provide a label saying how to find the values for the env var, so that fixing the error is more clear.

But feel free to ignore this, this is really cool and maybe this suggestion is premature

@MANTENN

This comment has been minimized.

Copy link

@MANTENN MANTENN commented Oct 18, 2019

I think it would be cleaner with hooks, and follow the hooks style. But again that's a matter of preference, and up to debate. Two options would be great.

@kachkaev

This comment has been minimized.

Copy link
Contributor

@kachkaev kachkaev commented Oct 18, 2019

To provide a seamless plugin experience, Next.js will add built-in support for auto-detecting packages with the naming convention @next/plugin- and next-plugin-.

I'd also add autodetection for @<scope>/next-plugin- like in Prettier. This will be useful for company-scoped internal plugins.

With autodetection, I'm curious how to handle cases when order of plugin execution matters. E.g. one might want to make Sentry's onErrorClient / onErrorServer to be outermost even if the same methods are defined by other plugins 🤔 We might need some kind of 'z-index' here, but as with z-index in CSS, assigned values can go a bit out of control one day 😅

@thedankelly

This comment has been minimized.

Copy link

@thedankelly thedankelly commented Oct 18, 2019

Can't wait. 👍🏻

@leerob

This comment has been minimized.

Copy link
Contributor

@leerob leerob commented Oct 19, 2019

I am so excited about this 🎉

Let me know about the Sentry plugin - willing to help out!

@sanishkr

This comment has been minimized.

Copy link

@sanishkr sanishkr commented Oct 19, 2019

Great idea. I will appreciate it if a repo link for full fledged sample next-plugin is provided. Also, any timelines on this?

@RichiCoder1

This comment has been minimized.

Copy link

@RichiCoder1 RichiCoder1 commented Oct 19, 2019

I share the same concern about loading order, as well as for

The only other required step for a plugin is to have a src directory with the lifecycle methods it wants to hook into.

It'd be nice if this could be configured for libraries that use transpilation so they can output to a separate folder.

Also it might be nice if a plugin could be organized as:

src/
  document/body-tags/server.js
  on-init/client.js
  on-init/server.js

though that may be overkill/perf problematic and a code smell for an overly large plugin.

We will also investigate allowing local plugins in a plugins or next-plugins directory that don't require being installed.

I think this would be super helpful for developing and testing plugins without mucking with linking/node_modules

@ematipico

This comment has been minimized.

Copy link

@ematipico ematipico commented Oct 19, 2019

It would be great if during the build stage, Next.js would be able to pass the routes of the application:

  • posts/:postId
  • contact-us

Thanks!

Edit: also, bear in mind that people usually put their final code inside a dist folder as they have plugins made using a different language (TypeScript). Does that mean that these plugins would need to compile their code into the same folder?

@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Oct 19, 2019

We also need ability to modify the webpack config, for example to make next-plugin-react-native-web.

We won't be exposing the webpack config to plugins as it's by far the easiest way to cause deoptimization. Instead we'll provide methods for aliasing modules for react-native-web for example.

@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Oct 19, 2019

#9133 (comment)

Initially we won't be supporting these as they also sound like pitfalls for deoptimization.

For example:

I'll use this to write that html to disk

Furthermore

A hook that provides me all the pages along with app
I'll use this on startup to call app.renderToHTML() for each page
This is essential because I can't wait for a client to request a page.

This is not possible as in development there is on-demand-entries.

@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Oct 19, 2019

#9133 (comment)

It's sort of dangerous to do so though, as it would be easy for you to forget providing environment variables in a certain environment and that would cause the plugin to either be excluded or error out based on the description.

Potentially we could do that behavior in development and fail if the env var is not set in production builds though.

@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Oct 19, 2019

#9133 (comment)

I think it would be cleaner with hooks, and follow the hooks style. But again that's a matter of preference, and up to debate. Two options would be great.

This comment is super confusing. Hooks has no relation to internal lifecycles (outside of React) which is what this RFC is about.

Could you elaborate what would be "cleaner". I'd argue it'd be much more confusing for users as these new methods have nothing to do with React directly.

@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Oct 19, 2019

#9133 (comment)

We already created a Sentry plugin to figure out which lifecycles are needed 👍

@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Oct 19, 2019

#9133 (comment)

As mentioned in other issues I generally don't share timelines. In general we release features incrementally starting with a minimal implementation and then iterate on that.

@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Oct 19, 2019

#9133 (comment)

I share the same concern about loading order, as well as for

Loading order shouldn't matter in the majority of cases. Hence why we didn't include it in the initial proposal. One thing I've been discussing internally is having a bailout option in next.config.js called plugins where you'd be able to define order if you really have to.

It'd be nice if this could be configured for libraries that use transpilation so they can output to a separate folder.

Plugins will go through the same compilation as other files in the project (pages etc). So they'll have the exact same configuration. One thing that we might want to keep in mind is TypeScript support, which should be easy to support.

Overall I'd strongly argue for not having plugin authors compile their code, it's very easy to deoptimize the code that way. Eg a wrong babel config would include unnecessary polyfills and a wrong TypeScript config would inline helpers.

Instead Next.js will ensure the code is optimized and compiled correctly. This is especially important as module/nomodule support is coming soon.

Also it might be nice if a plugin could be organized as:

That would make the structure much more complex for no real gain in my opinion.

@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Oct 19, 2019

#9133 (comment)

It would be great if during the build stage, Next.js would be able to pass the routes of the application:

What would the use-case be.

Edit: also, bear in mind that people usually put their final code inside a dist folder as they have plugins made using a different language (TypeScript). Does that mean that these plugins would need to compile their code into the same folder?

See my comment above 👍 #9133 (comment)

@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Oct 19, 2019

#9133 (comment)

I'd also add autodetection for @<scope>/next-plugin- like in Prettier. This will be useful for company-scoped internal plugins.

Far point, we forgot to write that down in the proposal. I'll update it 💯

@esamattis

This comment has been minimized.

Copy link

@esamattis esamattis commented Oct 19, 2019

Hi!

This is very exciting! We're actually building a framework thing on top of Nextjs static export feature and currently we are completely wrapping Nextjs to be able run our things before and after Nextjs does its things. For now we just import the export function from "next/dist/export".

So on top of my head here's few hooks we would need to create it as a plugin:

  • onNextDevStart
    • We have a watcher that automatically compiles TypeScript types from *.graphql files as user edits them.
  • onExportStart
    • Sending notification of export start. Would display it on a CMS admin panel
  • onPageExported
    • We'd like to send exporting progress to an external service (eg. a CMS) so we could display exporting progress indicator there
  • onExportDone
    • For generating sitemap.xml and robots.txt files to the exported output
    • Also for end notification like from onExportStart

Also could the plugins add #7208 like middleware?

@ematipico

This comment has been minimized.

Copy link

@ematipico ematipico commented Oct 19, 2019

What would the use-case be.

Serverless and lambdas.

I maintain a library that is like a bridge between terraform and next.js (and we have the same logic where I work). The routes are needed to configure the API Gateway. At the moment the routes are passed separately or calculated using the new next.js file structure. ([pageId].is).

So if next.js could provide the routes in a fashion manner, the integration with serverless services will be easier!

@Janpot

This comment has been minimized.

Copy link
Contributor

@Janpot Janpot commented Oct 19, 2019

What would the use-case be.

I'd like to optimize my i18n. Instead of it being a React context with a store of messages (like react-i18n or so), I want to bake in messages at build time. For this to work I'd like to alias the @locale module (or another identifier) to a folder based on the path like ./locales/en or ./locales/es. That way I could generate localized components inside of them, and import like:

import SomeMessage from '@locale/some-message';

In fact I'm only interested in 1 custom thing in the build stage based on the path, basically webpack aliases (resolve option)

Edit:

Just remembered I tested out this setup in a small sample repo a few years ago

Edit:

seems like I missed this:

Instead we'll provide methods for aliasing modules for react-native-web for example.

Would that apply to this use case, on a per-path basis?

@borekb

This comment has been minimized.

Copy link
Contributor

@borekb borekb commented Oct 20, 2019

@timneutkens

  1. Got it, thanks 👍.
  2. Looking at Gatsby plugins, for example, I don't think people are creating huge configs. But OK, it is some concern, I agree.
  3. I think I'm not confused – I was referring to a use case when I'm writing the plugin, not consuming it. Your API is file-based instead of function-based which is "strange" and I'm looking for reasons why it's that way. Again, if plugins were single-file + dynamic imports, what would be the problem?
@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Oct 20, 2019

Re, above:

  1. We exactly don't want that approach of having a single file.
  2. It's extremely easy to deoptimize if you don't. For example if it's a single file defining a variable in the module scope would already cause tree shaking for a module used to be opted out of. Instead with the separate file approach it's increasingly harder to deoptimize it.
@rlindskog

This comment has been minimized.

Copy link

@rlindskog rlindskog commented Oct 20, 2019

@epeli
#9133 (comment)

BTW, for in-development plugins, I'd probably like to use something like this:

plugin: '../my-plugins/nextjs-google-analytics',

I.e., standard Node module resolution.

It might be cool to automatically resolve "in-development" (local?) plugins - maybe by detecting a plugins folder?

Ex:

package.json
pages
  index.js
plugins
  styled-components
    on-error-client.js
    on-error-server.js
    on-init-client.js
    on-init-server.js 
@karlhorky

This comment has been minimized.

Copy link
Contributor

@karlhorky karlhorky commented Oct 21, 2019

First of all, thanks for this proposal, this is super exciting! 🚀


@borekb: I was surprised that plugins are "activated" just by being installed.

Yeah, for me auto-activating plugins just by installing is both cool (eg. I can understand the benefit) and also surprising (eg. maybe it could cause weird problems or not allow enough control).

For an example of "not enough control", I think about this comment from @kachkaev about situations where execution order matters (and I think this will not be uncommon to come up):

With autodetection, I'm curious how to handle cases when order of plugin execution matters. E.g. one might want to make Sentry's onErrorClient / onErrorServer to be outermost even if the same methods are defined by other plugins 🤔

Another point that I just thought of was about the potential danger of auto-loading transitive dependencies. For instance, consider:

  1. You install an unrelated dependency X that has a dependency Y on something that has been compromised similar to the event-stream compromise
  2. The compromise in dependency Y is that it installs a Next.js plugin that does something malicious to the site
  3. You do not notice that a Next.js plugin has been installed and you deploy your site to production
  4. Something bad happens 💥

But maybe transitive dependencies won't be auto-loaded? I suppose this comment suggestions they won't be:

@timneutkens: It did make me think that eg material-ui would be able to automatically configure Next.js without you having to add next-plugin-material-ui or similar.


Either way, it feels like having an ordered plugins array in the Next.js config would be a less magic, more careful and controlled way of adding plugins.

Like Gatsby does it, for example: https://www.gatsbyjs.org/docs/gatsby-config/#plugins

@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Oct 21, 2019

@karlhorky The security argument doesn't hold true because the loading is backed by package.json in your project, sub-deps wouldnt' be loaded.

I'm not opposed to have a bailout method through a plugins key if you really want to opt-out of automatic loading though.

@karlhorky

This comment has been minimized.

Copy link
Contributor

@karlhorky karlhorky commented Oct 22, 2019

The security argument doesn't hold true because the loading is backed by package.json in your project, sub-deps wouldnt' be loaded.

Yep, expected as much. 👍

So it would be relevant in fewer cases then, such as when users install something accidentally (for example, a package with a long install string, where the user doesn't check which packages are in it), but these may prove to be acceptable levels of risk.

I'm not opposed to have a bailout method through a plugins key if you really want to opt-out of automatic loading though.

This sounds like a reasonable compromise: zero-config by default, but if you want control, you can opt in.

@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Oct 22, 2019

So it would be relevant in fewer cases then, such as when users install something accidentally (for example, a package with a long install string, where the user doesn't check which packages are in it), but these may prove to be acceptable levels of risk.

Sounds strange to me. Especially this part:

such as when users install something accidentally (for example, a package with a long install string, where the user doesn't check which packages are in it)

This sounds very unlikely and I'd argue that at that point it doesn't really matter if you're using Next.js or not, your laptop would already be compromised because of pre-install / post-install scripts with any dependency.

@karlhorky

This comment has been minimized.

Copy link
Contributor

@karlhorky karlhorky commented Oct 22, 2019

Yep, I agree that this is strange behavior. But I've seen it a lot from developers in the wild. Shouldn't pass code review though, so hopefully not as present as it could be.

The difference between pre-/post-install risk and auto-loading packages is that auto-loading loads code many more times across more environments, whereas pre-/post-install scripts load code once at install time.

The contract of having to import packages to trigger running the code contained in them every time your application starts can be seen as a security measure, one that would no longer exist with auto-loading.

But again, like I said, maybe this is an acceptable level of risk.

@evantahler

This comment has been minimized.

Copy link
Contributor

@evantahler evantahler commented Oct 23, 2019

Just chiming in to say that I'm I'm very excited about this and happy to help!
We've been monkey patching a way to let plugins add their own pages for a while now, as described here https://spectrum.chat/next-js/general/creating-an-application-with-front-end-plugins~ed8926da-62bf-438d-8916-172900b3e9bb ... and it's less than optimal :D

@jth0024

This comment has been minimized.

Copy link

@jth0024 jth0024 commented Oct 24, 2019

I just want to chime in that ordering of plugins will be very important. I actually built a lightweight plugin system on top of NextJS for my company. We initially wanted to auto load plugins from a directory to match NextJS’s convention over configuration approach, but we quickly ran into two big issues.

  1. plugins will need complex data passed to them
  2. plugin order matters

Let me expand on this a bit. I think many useful plugins will need complex data that can't be provided as environment variables. You mentioned that setting up redux was a common use case. Both next-redux-wrapper and my internal redux plugin require either a makeStore function or middleware, enhancers, and initialReducers. Would your solution accommodate those use cases?

As for plugin order, this matters because it’s very common that other plugins might depend on one loaded before them. For example, one plugin might depend on the initialization of another. Imagine a config plugin and a redux plugin. The config must be initialized first so that the redux plugin can check config.loggingEnabled before conditionally applying logger middleware. Without plugin ordering, this use case would be impossible.

Just some food for thought! Don’t hesitate to reach out if you want some more info about the solution we implemented. Very excited about this!

@HaNdTriX

This comment has been minimized.

Copy link
Contributor

@HaNdTriX HaNdTriX commented Nov 2, 2019

Plugin Scope

Next.js transitioned in the last version (v9.x.x) to a more page based approach.
Instead of installing things on global (_app.js) scope we prefer now a local (page centric) scope.

Examples are the new with-apollo or with-redux examples.

How do plugins fit into this context. Are plugins always global (enabled project wide) or will it be possible do enable/disable plugins on page level?

@satazor

This comment has been minimized.

Copy link

@satazor satazor commented Nov 2, 2019

We won't be exposing the webpack config to plugins as it's by far the easiest way to cause deoptimization. Instead we'll provide methods for aliasing modules for react-native-web for example.

@timneutkens This will limit the plugins usefulness. Currently, Next.js already provides a way to change the webpack config via webpack() in next.config.js. In fact, the "unofficial" way plugins are set right now is to compose various libraries (aka "plugins") in your next.config.js, where all these libs can already modify the webpack config.

I understand you are trying to be protective by limiting people from doing bad things, but you are also limiting experienced people from doing great things.

@satazor

This comment has been minimized.

Copy link

@satazor satazor commented Nov 2, 2019

I would also would like to say that this is great, and will make the ecosystem healthier. From what I could evaluate, Gatsby's plugin system is nice and it might be worth taking a look at it to get some inspiration.

@jkrems

This comment has been minimized.

Copy link

@jkrems jkrems commented Nov 20, 2019

One use case I haven't heard mention yet: (API) routes provided by a plugin. Examples could be a GraphQL endpoint or (in my case) dynamically generated scripts. Right now that requires creating a file in pages/ even if that file is just a one-liner re-exporting the plugin implementation of a request handler.

@brad-decker

This comment has been minimized.

Copy link

@brad-decker brad-decker commented Nov 20, 2019

@timneutkens this proposal excites me, would allow us to start tearing down our custom _document.js file which has grown into a monster. I see that you're already starting to test this with the material-ui / google analytics plugin. Looks like exciting stuff. Right now we're doing styled-components + material-ui in _document and it looks pretty horrific. With a plugin system we'd be able to separate those into two different local plugins that'd be pretty great.

👍

@timneutkens

This comment has been minimized.

Copy link
Member Author

@timneutkens timneutkens commented Nov 21, 2019

@brad-decker tbh I don't feel like that would be super great, it means you're already using 2 css-in-js solutions in your app.

@brad-decker

This comment has been minimized.

Copy link

@brad-decker brad-decker commented Nov 21, 2019

@timneutkens we are using the material ui core components but are using styled-components as our preferred method of extending those styles. Material-ui will be moving its base engine to styled-components "soon" https://material-ui.com/guides/interoperability/ but i do agree that it's worrisome. Are there any gotchas i should be worried about with this setup from the next perspective?

@jacobrask

This comment has been minimized.

Copy link

@jacobrask jacobrask commented Nov 21, 2019

In production apps you are likely to at least at some point (during a migration) use more than one css-in-js solution, unless everyone selects the right library the first time and never switch.

@brad-decker

This comment has been minimized.

Copy link

@brad-decker brad-decker commented Nov 21, 2019

@jacobrask -- true, but this feels a little ... bad.

 ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: App => props =>
            sheet.collectStyles(materialSheets.collect(<App {...props} />)),
        });

@samjbmason

This comment has been minimized.

Copy link

@samjbmason samjbmason commented Jan 6, 2020

I can see it was mentioned in the initial outline but will there be a way to develop plugins locally without the need to creating a npm package and linking it?

@Ianfeather

This comment has been minimized.

Copy link

@Ianfeather Ianfeather commented Jan 10, 2020

👋 Hi there, is there a timeline for this landing?

@hugo

This comment has been minimized.

Copy link

@hugo hugo commented Jan 17, 2020

I can see it was mentioned in the initial outline but will there be a way to develop plugins locally without the need to creating a npm package and linking it?

You can do this by using a local path for the package. For example I have made a plugin for adding a polyfill.io <script> tag to every page. The package is in packages/next-plugin-polyfill of my project directory. In my package.json I have (other details elided):

{
  "dependencies": {
    "next-plugin-polyfill": "file:plugins/next-plugin-polyfill"
  }
}

When you run npm install (or npm ci) npm will symlink your local directory into node_modules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.