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

Fontsource Compile Plugin #234

Closed
ayuhito opened this issue May 23, 2021 · 9 comments
Closed

Fontsource Compile Plugin #234

ayuhito opened this issue May 23, 2021 · 9 comments
Assignees
Labels
enhancement New feature or request needs community input Needs additional discussion

Comments

@ayuhito
Copy link
Member

ayuhito commented May 23, 2021

This is a proposal to release @fontsource/plugin-compile which aims to compile CSS and SCSS on build time to allow full developer flexibility on what their CSS/SCSS should contain.

Similar to the PostCSS suggestion (#133), this would allow developers to adjust default values such as font-display: swap or src: url(...) to anything else they want. The customizability would be limited to all that @font-face has to offer.

Now I'm not sure exactly what would be the best approach to execute this in build time so I'm open to suggestions. The two approaches I have in mind are either:

  1. A script, e.g. npx fontsource that you run prebuild for your project which generates a custom CSS file that could be imported normally - import @fontsource/plugin-compile/custom.css. You'd still need to install a font package for the compiler to have font files to work with. You'll also need to select your options via a config file like fontsource.config.json, creating a fontsource property in your package.json or perhaps just using flags in the command line.

I like this approach a lot because it's framework agnostic and keeps things simple.

  1. Load the plugin via your Webpack, ESBuild config etc.

This approach I feel is a lot more intensive as we'd need to maintain multiple types of plugins for each bundler or direct integrations with a framework such as Gatsby.

Both approaches feel like a lot work for very little customizability that the @font-face selector actually offers. It's a niche feature as the defaults work for 99% of usecases. I feel that the 1% who do need that customizability should then just manually handle things, but I'm open to see if there is interest for something like this.

@ayuhito ayuhito added enhancement New feature or request contributors welcome! Open to outside contributors needs community input Needs additional discussion labels May 23, 2021
@ayuhito ayuhito closed this as completed Jun 17, 2021
@ayuhito ayuhito reopened this Jan 14, 2022
@jwr1
Copy link
Member

jwr1 commented Jan 14, 2022

@DecliningLotus, if you're still considering this issue, one option we could use to create the bundler plugin is unplugin. It's a unified plugin system supporting Vite, Rollup, Webpack 4 & 5, and esbuild. The API is based off the Rollup plugin API.

@ayuhito
Copy link
Member Author

ayuhito commented Jan 18, 2022

That's really interesting, but honestly seeing the number of different bundlers really puts me off going with the second option. I think there are more points of failure and maintenance vs just generating a custom.css file.

@ayuhito
Copy link
Member Author

ayuhito commented Feb 4, 2022

Specification

As time has passed it's become evident that this plugin actually seems to be quite useful to many developers. I'm thinking a CLI tool that also has a programmatic API is ideal for this. It would also help make the project even more framework independent.

Commands

npx fontsource roboto inter - Base command with support for multiple fonts. You would also need to install the relevant font packages e.g. @fontsource/roboto and @fontsource/inter.

-o | --output directory/file - A custom location to output the CSS file. Default is in node_modules/@fontsource/plugin-compile/custom.css. Note that everytime yarn add, npm install etc, is run, the custom.css will be wiped by yarn/NPM if you are using the default output directory in node_modules, hence you'd need to run it every time prebuild.

--copy-files - This copies all needed font files from @fontsource/font-name into the -o output directory if the default is not used. Super useful for those who cannot use a bundler like Webpack and really need the files in a separate location.

--no-css - Could be used in conjunction with --copy-files so only font files are copied and CSS isn't generated.

--no-variable - I'm considering the default behaviour to include variable fonts if available. Although using @supports on @font-face making it the compilers responsibility, or making it the developers responsibility to apply it to font-family is still left up to debate.

--no-fallback - This removes the @supports fallback CSS code for browsers that do not support variable fonts.

-s | --style normal,italic - Select font-style or both if comma separated. Default is normal.

-w | --weight 400,500,600 - Select font-weight. Default is 400.

-d | --display swap - Select font-display option. Default is swap.

Each of these flags could also be automatically read from a config file, such as .fontsourcerc or fontsource.json, or programmatically run via an API through Node.

Let me know if there should be any additional commands for this!

References

#385 (comment) - Discusses edge cases the plugin will need to account for.

@jwr1
Copy link
Member

jwr1 commented Feb 4, 2022

I still feel even with this option that a bundler plugin would be useful. You mentioned this would have to be run whenever it's reinstalled, that could be done automatically at build time. If you are using a bundler, you will also need to run it again whenever changes are made to a configuration (especially in development mode), this could also be done automatically. I think the above should be the base for a bundler plugin as well as a fallback for those not using a bundler.

@ayuhito
Copy link
Member Author

ayuhito commented Feb 4, 2022

I think the above should be the base for a bundler plugin as well as a fallback for those not using a bundler.

Would that mean developing for both cases?

If you are using a bundler, you will also need to run it again whenever changes are made to a configuration (especially in development mode), this could also be done automatically.

I don't think it's a big deal. A recommendation in the documentation to use an NPM postinstall or prebuild script would help developers make things more automatic. I don't expect many changes to be made to the configuration file so often in development for it to become a major annoyance. Moreso I'm expecting developers to not use the default output configuration, where this issue is nonexistent.

A large motivation for me using the non-bundler approach is the fact that I've seen this project be used in very very unexpected places, such as a Ruby or Python codebase, where they used wildly hacky methods to get Fontsource useful to them. Having no dependency would allow the project to be used with huge variation.

And this doesn't discontinue the existence of the original way to use Fontsource via imports directly. This plugin really just accounts for niche cases.

@jwr1
Copy link
Member

jwr1 commented Feb 4, 2022

Would that mean developing for both cases?

No, I think we could just use the original idea you mentioned and just reference the node API from within a bundler plugin, the CLI and node API could be exactly the same as in the specification. Obviously, we would still need to create the bundler plugin itself, but that should be fairly easy as most of the work will happen in the original CLI / node API tool.

If developers happen to use a bundler, then they can use the bundler plugin, if they don't use a bundler then they can use the CLI or node API mentioned in the specification. The bundler plugin should not really interfere with the original specification, it should just take advantage of it and be a convenience to those that happen to be using a bundler.

@ayuhito ayuhito removed the contributors welcome! Open to outside contributors label Mar 11, 2022
@ayuhito ayuhito self-assigned this Mar 26, 2022
@ayuhito ayuhito mentioned this issue Apr 27, 2022
@michaelfaith
Copy link

Default is in node_modules/@fontsource/plugin-compile/custom.css. Note that everytime yarn add, npm install etc, is run, the custom.css will be wiped by yarn/NPM if you are using the default output directory in node_modules, hence you'd need to run it every time prebuild.

I'm not sure writing directly to node_modules is a good approach, for the reason you mentioned, but also would likely be problematic for people using newer versions of yarn with PnP.

@ayuhito
Copy link
Member Author

ayuhito commented Apr 27, 2022

I'm not sure writing directly to node_modules is a good approach, for the reason you mentioned, but also would likely be problematic for people using newer versions of yarn with PnP.

Ah, yeah. I hadn't updated this issue but I removed that as a default when working a little on this. An outdir is now required, not optional.

@ayuhito
Copy link
Member Author

ayuhito commented May 21, 2023

I don't think this is necessary anymore with the new CLI from #590. If we are missing features, we can plan to extend that.

@ayuhito ayuhito closed this as completed May 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request needs community input Needs additional discussion
Projects
None yet
Development

No branches or pull requests

3 participants