Edit by @david: Discourse’s theming system now has built-in support for multiple JS files. This webpack method is no longer required.
Hi! So while I was developing my handsfree-discourse component, I hit a few problems around file management. My main issue is that I needed a way to break up my code across multiple files. The other issue was that I needed to include 3rd party libraries without having to ask admins to enable CORS or trigger additional HTTP requests.
To solve these issues I made discourse-webpack, a boilerplate to quickly scaffold JS-heavy components! Features include:
- Local dev server with live reloading
- Includes a commit script to keep your source code and compiled code in separate branches!
The rest of this topic explains how to use it and why it works. I literally just finished testing this for a few other components I’m working on, so let me know if you run into any problems or have any specific requests!
Discourse Webpack
Quickly scaffold JavaScript-heavy components for your Discourse Community, complete with a commit script to keep your source code and build code in separate branches to help you keep shipping fast!
Install
First, make sure you have NodeJS >= 8 and git installed locally on your machine. Then, type each of the lines below:
# Download this repository
git clone https://github.com/browsehandsfree/discourse-webpack
# Move into the directory
cd discourse-webpack
# Install dependencies
npm install
You’ll then need to edit the following in package.json
, replacing all of our links with yours. Specifically:
{
name: 'your-project',
repository: {
url: 'git+https://github.com/username/repo'
},
author: '',
bugs: {
url: 'https://github.com/username/repo/issues'
},
homepage: 'https://example.com'
}
Most importantly of all, make sure repository.url
is correct and is prefaced with git+
. When you run npm run discourse
, it’ll commit and push to that repo.
Also, don’t forget to set your Discourse’s about.json
, which is located in /src/discourse/about.json
Development
After npm install
, you’ll end up with the following directory structure:
discourse-webpack
|- node_modules/ # Dependencies
|- src/ # The main source files
|--|- discourse/ # Discourse theme files
|--|--|- common/
|--|--|- desktop/
|--|--|- mobile/
|--|- main.css # The main stylesheet
|--|- main.js # The main Javascript entry
|--|- sandbox.html # Sandbox for local development
|- .gitignore
|- discourse-push.js # Special commit script
|- README.md
|- webpack.config.js # Webpack config
|- yarn.lock
Command Line Scripts
Additionally, you have access to the following commands from the project root:
# Launch a dev server on localhost:8080
# - Supports livereload
# - Uses `/src/sandbox.html` to help you debug locally
npm run dev
# Compile your component into `/dist`
npm run build
# Compile your component into `/dist`
# - Then commits `/dist` into the `discourse` branch
npm run discourse
How it works
Once you’ve downloaded the repo and installed dependencies it’s time to start developing! Use npm run dev
to start a livereload server on localhost:8080
.
Visiting that URL will load the HTML file located in /src/sandbox.html
. This file isn’t actually used within Discourse, and is just here to help you develop your scripts locally (outside the context of Discourse).
The main webpack entry point is /src/main.js
. From there, you can import
other scripts and webpack will bundle everything together and inject them into the following files:
/src/sandbox.html
/src/discourse/common/body_tag.html
main.js
is compiled and injected into sandbox.html
automatically, but is manually injected inline with body_tag.html
because of the following code:
<script>
<%= compilation.assets['main.js'].source() %>
</script>
If you wanted to inject your script into another template, like after_header.html
, you would just copy that script
tag into that template instead. This allows you to use keep the HTML and JavaScript for that template separated while developing…but concatenated when deployed!
Compiling
When you compile with npm run build
, what’s happening is:
- First,
/src/main.js
and dependencies are bundled - Then, all files in
/src/discourse/
are copied over to/dist/
- At the same time,
main.js
is injected inline in any template file that contains:
<script>
<%= compilation.assets['main.js'].source() %>
</script>
Deploying
When you run npm run discourse
, the /discourse-push.js
script is called and does the following:
- First it’ll compile, as if with
npm run build
- Then, it’ll initialize a new git repo inside of
/dist
- It then commits
/dist
into your projectsdiscourse
branch (it’ll create the branch if it doesn’t exist)
Using the discourse
branch
Each of the following
/relative/urls/
are relative to your forum’s base URL, eg, https://example.com/relative/urls/
Install the component
Install your component by visiting /admin/customize/themes
and “Import from the web” from your projects repository, eg: https://github.com/my-awesome/discourse-component
.
Then set the branch to discourse
. It won’t work if you leave it at master
, since Discourse will try to load the uncompiled files (if it works at all).
Debugging theme specific files on your own host
- Install the Discourse Theme CLI
- Log into https://theme-creator.discourse.org
- CD into this directory, then run
discourse_theme watch .
- Use
https://theme-creator.discourse.org
as the base URL- Use your API key from
theme-creator
- Use your API key from
If you’re new to Discourse and would like to fork this project, the following reads might be helpful.