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

Provide a yarn add step for gem plugins with the relevant metadata when they get loaded #8

Merged
merged 1 commit into from Apr 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 26 additions & 0 deletions bridgetown-core/lib/bridgetown-core/plugin_manager.rb
Expand Up @@ -26,6 +26,7 @@ def self.require_from_bundler

Bundler.setup
required_gems = Bundler.require(:bridgetown_plugins)
install_yarn_dependencies(required_gems)
message = "Required #{required_gems.map(&:name).join(", ")}"
Bridgetown.logger.debug("PluginManager:", message)
ENV["BRIDGETOWN_NO_BUNDLER_REQUIRE"] = "true"
Expand All @@ -36,6 +37,31 @@ def self.require_from_bundler
end
end

# Iterates through loaded plugins and finds yard-add gemspec metadata.
# If that exact package hasn't been installed, execute yarn add
#
# Returns nothing.
def self.install_yarn_dependencies(required_gems)
return unless File.exist?("package.json")

package_json = JSON.parse(File.read("package.json"))

required_gems.each do |loaded_gem|
next unless loaded_gem.to_spec&.metadata&.dig("yarn-add")

yarn_add_dependency = loaded_gem.to_spec.metadata["yarn-add"].split("@")
next unless yarn_add_dependency.length == 2

# check matching version number is see if it's already installed
current_package = package_json["dependencies"].dig(yarn_add_dependency.first)
next unless current_package.nil? || current_package != yarn_add_dependency.last

# all right, time to install the package
cmd = "yarn add #{yarn_add_dependency.join("@")}"
system cmd
end
end

# Require all .rb files
#
# Returns nothing.
Expand Down
24 changes: 21 additions & 3 deletions bridgetown-website/src/_docs/frontend-assets.md
Expand Up @@ -11,19 +11,37 @@ Bridgetown comes with a default configuration of [Webpack](https://webpack.js.or

Files to be processed by Webpack are placed in the top-level `frontend` folder within your site root. This folder is entirely separate from the Bridgetown source folder where your content, templates, plugins, etc. live. However, using relative paths you can reference files from Webpack that live in the source folder (so you could keep CSS partials alongside Liquid templates, for example).

Bridgetown recommends using [Yarn](https://yarnpkg.com) to install and manage frontend packages and dependencies, but if you prefer using NPM that's perfectly fine.
Bridgetown uses [Yarn](https://yarnpkg.com) to install and manage frontend NPM-based
packages and dependencies.
[Gem-based plugins can instruct Bridgetown](/docs/plugins/gems-and-webpack/) to add
a related NPM package whenever Bridgetown first loads the gem.

## Javascript

The starting place for Javascript code lives at `./frontend/javascript/index.js`. Here you can write your custom functionality, use `import` statements to pull in other modules or external packages, and so forth. This is also where you'd import all relevant CSS. (By default it imports `./frontend/styles/index.scss`.)

Because Bridgetown utilizes standard Webpack functionality, you can trick out your Javascript setup with additional language enhancements like Typescript or add well-known frameworks like React, Vue, Stimulus, and many others.
Because Bridgetown utilizes standard Webpack functionality, you can trick out your Javascript setup with additional language enhancements like Typescript or add well-known frameworks like React, Vue, Stimulus, and many others. For example,
to add slick page transitions to your website using [Swup](https://swup.js.org/), you would simply run:

```sh
yarn add swup
```

And then update `./frontend/javascript/index.js` with:

```js
import Swup from "swup"

const swup = new Swup()
```

And the update your HTML layout according to the Swup install guide.

## CSS

The starting place for CSS code lives at `./frontend/styles/index.scss`. By default Bridgetown uses [Sass](https://sass-lang.com), a pre-processor for CSS, but you can customize your Webpack config to change that to use standard `PostCSS` which is popular with the Webpack community.

Importing common CSS frameworks such as Bootstrap, Foundation, Bulma, Tailwind, and so forth is often as easy as running
Importing common CSS frameworks such as Bootstrap, Foundation, Bulma, Tailwind, and so forth is often as easy as running:

```shell
$ yarn add name-of-css-framework
Expand Down
36 changes: 20 additions & 16 deletions bridgetown-website/src/_docs/plugins.md
Expand Up @@ -7,9 +7,13 @@ category: plugins

Plugins allow you to extend Bridgetown's behavior to fit your needs. These guides help you with the specifics of creating plugins. We also have some recommended best practices to help structure your plugin.

{:.note}
{% rendercontent "docs/note", title: "Roll It All Up in a Gem" %}
If you'd like to maintain separation from your site source code and
share functionality across multiple projects, we suggest creating a gem for your plugin. This will also help you manage dependencies, For tips on creating a gem take a look a the [Ruby gems guide](https://guides.rubygems.org/make-your-own-gem/) or look through the source code of an existing plugin such as _bridgetown-feed_.
share functionality across multiple projects, we suggest creating a gem for your plugin. This will also help you manage dependencies. For tips on creating a gem take a look a the [Ruby gems guide](https://guides.rubygems.org/make-your-own-gem/) or look through the source code of an existing plugin such as [bridgetown-feed](https://github.com/bridgetownrb/bridgetown-feed).

Make sure you [follow these instructions](/docs/plugins/gems-and-webpack/) to integrate your plugin's frontend code
with the users' Webpack setup!
{% endrendercontent %}

## Installation

Expand All @@ -33,41 +37,41 @@ There are two methods of adding plugins to your site build.

There are six types of plugins in Bridgetown.

### Tags
### [Tags](/docs/plugins/tags/)

[Tags](/docs/plugins/tags/) create custom Liquid tags which you can add to your content or design templates. For example:
Tags create custom Liquid tags which you can add to your content or design templates. For example:

* _bridgetown-youtube_
* [_bridgetown-seo-tag_](https://github.com/bridgetownrb/bridgetown-seo-tag)

### Filters
### [Filters](/docs/plugins/filters/)

[Filters](/docs/plugins/filters/) create custom Liquid filters to help transform data and content. For example:
Filters create custom Liquid filters to help transform data and content. For example:

* _bridgetown-time-ago_

### Generators
### [Generators](/docs/plugins/generators/)

[Generators](/docs/plugins/generators/) create new content on your site in an automated fashion, perhaps via external APIs.
Generators create new content on your site in an automated fashion, perhaps via external APIs.
For example:

* _bridgetown-feed_
* [_bridgetown-feed_](https://github.com/bridgetownrb/bridgetown-feed)

### Converters
### [Converters](/docs/plugins/converters/)

[Converters](/docs/plugins/converters/) change a markup language from one format to another. For example:
Converters change a markup language from one format to another. For example:

* _bridgetown-textile-converter_

### Commands
### [Commands](/docs/plugins/commands/)

[Commands](/docs/plugins/commands/) extend the `bridgetown` executable with
Commands extend the `bridgetown` executable with
subcommands. For example:

* _bridgetown-compose_

### Hooks
### [Hooks](/docs/plugins/hooks/)

[Hooks](/docs/plugins/hooks/) provide fine-grained control to trigger custom functionality at various points in the build process.
Hooks provide fine-grained control to trigger custom functionality at various points in the build process.

## Tips for Plugin Development

Expand Down
42 changes: 42 additions & 0 deletions bridgetown-website/src/_docs/plugins/gems-and-webpack.md
@@ -0,0 +1,42 @@
---
title: Gem-based Plugins and Webpack
hide_in_toc: true
order: 0
category: plugins
---

{% render "docs/help_needed", page: page %}

When authoring a plugin for Bridgetown, you may find yourself wanting to ensure users
of your plugin are able to load in your frontend assets through Webpack (such as
Javascript, CSS, etc.) The best way to do this is to set up a `package.json`
manifest and [publish your frontend code as a package to the NPM registry](https://docs.npmjs.com/creating-node-js-modules#create-the-file-that-will-be-loaded-when-your-module-is-required-by-another-application).

Let's assume you've been building an awesome plugin called, unsurprisingly,
`MyAwesomePlugin`. In your `my-awesome-plugin.gemspec` file, all you need to do is
add the `yarn-add` metadata matching the NPM package name and keeping the version
the same as the Gem version:

```ruby
spec.metadata = { "yarn-add" => "my-awesome-plugin@#{MyAwesomePlugin::VERSION}" }
```

With that bit of metadata, Bridgetown will know always to look for that package in
the users' `package.json` file when they load Bridgetown, and it will trigger a
`yarn add` command if the package and exact version number isn't present.

{% rendercontent "docs/note", title: "Make sure you update package.json!", type: "warning" %}
If you bump up your Ruby version number and forget to bump the NPM package version
at the same time, the packages will get out of sync! So remember always to update
`version.rb` and `package.json` so they have the same version number.
{% endrendercontent %}

You will need to instruct your users how to add the plugin's frontend code to their
Webpack entry points. For example, they might need to update `frontend/javascript/index.js` with:

```js
import MyAwesomePlugin from "my-awesome-plugin"

const awesomeness = new MyAwesomePlugin()
awesomeness.doCoolStuff()
```
Expand Up @@ -42,7 +42,7 @@ In [a short amount of time](/about/#roadmap), Bridgetown has introduced a slew o

That's why all these changes being made to the codebase now, while perhaps painful in the short term for anyone wanting to quickly migrate from Jekyll to Bridgetown, are vital and necessary, because **we're planning for the next ten years of [Jamstack](/docs/jamstack) technology innovation**.

This includes our **whole-hearted embrace of [Webpack](https://webpack.js.org)**. Webpack (and similar Javascript tools like it) has in fairly short order become absolutely indispensable to modern frontend web development—to the point that I would argue any website framework which _doesn't_ use a tool like Webpack to manage frontend dependencies (along with NPM/Yarn) is _actively harming_ its developer community.
This includes our **[whole-hearted embrace of Webpack](/docs/frontend-assets/)**. Webpack (and similar Javascript tools like it) has in fairly short order become absolutely indispensable to modern frontend web development—to the point that I would argue any website framework which _doesn't_ use a tool like Webpack to manage frontend dependencies (along with NPM/Yarn) is _actively harming_ its developer community.

Part of the reason people turn to software frameworks to build things is to get **good defaults**. You want something that comes with [everything you need](https://rubyonrails.org/everything-you-need/) to start off right so you don't have to reinvent the wheel or get lost in an industry dead end. This is an active and ongoing focus for Bridgetown, from how the software gets installed, to configuring typical settings and plugins, to best practices in building and deploying the final site.

Expand Down
3 changes: 1 addition & 2 deletions bridgetown-website/src/about.md
Expand Up @@ -22,8 +22,7 @@ As of spring 2020, here is the vision for where Bridgetown is headed. And this i
- ✅ _DONE!_ **Streamline internals** to remove deprecated or legacy code paths and reduce confusing configuration options.
- ✅ _DONE!_ **Improve default site file/folder structure** to bring Bridgetown in line with other popular static site generators.
- ✅ _DONE!_ Add a `bridgetown console` command to **interactively interact with the site data and plugins** (just like the Rails console).
- ✅ _DONE!_ Remove the aging asset pipeline and **regroup around a modern solution: Webpack**. (Similar to how Rails adopted Webpack and distanced itself from Sprockets.)
- ✳️ _IN PROGRESS…_ Add additional commands to **further cement the Webpack build process** into the Bridgetown build process.
- ✅ _DONE!_ Remove the aging asset pipeline and **regroup around a modern solution: Webpack**. (Similar to how Rails adopted Webpack and distanced itself from Sprockets.) [Check out the preliminary documentation here.](/docs/frontend-assets/)
- ✅ _DONE!_ Integrate **pagination features** directly into the monorepo.
- ✅ _DONE!_ Move most site data vars to a **reloadable file** (aka `_data/site_metadata.yml`). Coming soon: env-specific settings (development vs. production).
- ✳️ _IN PROGRESS…_ Modernize various aspects of the codebase, incrementally **improving
Expand Down