-
Notifications
You must be signed in to change notification settings - Fork 9
Home
The MWDK is an NPM package that allows developers to make widgets independent of the Materia platform, with live reloading and a handful of additional features to facilitate faster development. Additional documentation related to the MWDK's features are available on the docs site.
- Node v16 or later
- Yarn
To install MWDK, run:
yarn add materia-widget-development-kit
MWDK should then be listed under the dependencies
section of your widget's package.json
:
"dependencies": {
"materia-widget-development-kit": "3.0.0"
}
Note that this is a required dependency of all Materia widgets.
Additionally, the following entries must be added to the scripts
section of your widget's package.json
:
"start": "mwdk-start",
"build": "mwdk-build-prod",
"build-dev": "mwdk-build-dev",
What each script does:
- mwdk-start: This starts the Express server in development mode.
- mwdk-build-prod: This builds webpack in production mode. See the output in /build folder.
- mwdk-build-dev: This builds webpack in development mode. See the output in /build folder.
While both may work, we do not maintain a NPM lockfile (package-lock.json
or npm-shrinkwrap.json
) in the repo. Therefore, we recommend using yarn.
The bane of everyone's existence, Webpack. Here's a rundown of what you'll need to compile your widget correctly!
See an example configuration for React.
The entries is an object containing your source files. Each entry is an array of files that make up a page in your widget, such as the player, creator, and score screen. Each entry should list the HTML file first, followed by any JavaScript files and CSS files. This order is essential for Webpack to generate the necessary files.
Example entries object for a React widget
const entries = {
'player': [
path.join(srcPath, 'player.html'),
path.join(srcPath, 'player.js'),
path.join(srcPath, 'player.scss')
],
'creator': [
path.join(srcPath, 'creator.html'),
path.join(srcPath, 'creator.js'),
path.join(srcPath, 'creator.scss')
],
'scoreScreen': [
path.join(srcPath, 'scoreScreen.html'),
path.join(srcPath, 'scoreScreen.js'),
path.join(srcPath, 'scoreScreen.scss')
]
}
NOTE: If you include CSS files in your React files (e.g. import './some-component.scss'
), then you don't need to include the CSS file in the entry array.
Example entries object for an AngularJS widget
const entries = {
'creator': [
path.join(srcPath, 'creator.html'),
path.join(srcPath, 'creator.coffee'),
path.join(srcPath, 'creator.scss'),
],
'player': [
path.join(srcPath, 'player.html'),
path.join(srcPath, 'player.coffee'),
path.join(srcPath, 'player.scss'),
],
'scorescreen': [
path.join(srcPath, 'scorescreen.html'),
path.join(srcPath, 'scorescreen.coffee'),
path.join(srcPath, 'scorescreen.scss'),
]
}
Can I use the default entries? Yes! The MWDK does provide default entries; however, we recommend creating your own entries since they will be different depending on the technology stack you're using.
What's included in the default entries?
const srcPath = path.join(process.cwd(), 'src') + path.sep
const getDefaultEntries = () => ({
'creator': [
`${srcPath}creator.html`,
`${srcPath}creator.js`,
`${srcPath}creator.scss`
],
'player': [
`${srcPath}player.html`,
`${srcPath}player.js`,
`${srcPath}player.scss`
]
})
This is an array of source files that we'd like to copy over to the final build. We highly recommend looking at what is already being copied by default (see below) so you don't have to write any additional code.
How to get the default copy list from the MWDK and append any assets you'd like to copied:
const widgetWebpack = require('materia-widget-development-kit/webpack-widget')
const copy = widgetWebpack.getDefaultCopyList()
const outputPath = path.join(process.cwd(), 'build')
const copyList = copy.concat([
{
from: path.join(__dirname, 'src', '_guides', 'assets'),
to: path.join(outputPath, 'guides', 'assets'),
toType: 'dir'
},
])
What's included in the default copy list?
The MWDK will check to see if these files exist; if so, it will copy them over.
const defaultCopyList = [
{
from: `${srcPath}demo.json`,
to: `${outputPath}demo.json`,
},
{
from: `${srcPath}install.yaml`,
to: outputPath,
},
{
from: `${srcPath}_icons`,
to: `${outputPath}img`,
toType: 'dir'
},
{
from: `${srcPath}_score`,
to: `${outputPath}_score-modules`,
toType: 'dir'
},
{
from: `${srcPath}_screen-shots`,
to: `${outputPath}img/screen-shots`,
toType: 'dir'
},
{
from: `${srcPath}_screen-shots`,
to: `${outputPath}img/screen-shots`,
toType: 'dir'
}
]
Also known as webpack loaders, these define what to do with your files.
How to grab the default rules:
const rules = widgetWebpack.getDefaultRules()
How to append a custom loader:
const myCustomLoader = {
// do something!
}
const customRules = [
...rules,
myCustomLoader
]
If you wanted to include only a few of the default rules:
const customRules = [
rules.reactLoader,
rules.loadHTMLAndReplaceMateriaScripts,
rules.loadAndPrefixSASS,
rules.copyImages,
myCustomLoader
]
Here are the names for each of the default rules and what they do. You do not need to transfer the code samples into your own code. They are only here to make it transparent exactly they're doing. See above for how to properly include them.
reactLoader
The React Loader uses [Babel](https://babeljs.io/). This loader finds any .js and .jsx files and converts them to JavaScript that all browsers will understand.
reactLoader: {
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react'
]
}
}
},
loaderDoNothingToJs
This loader is used for processing regular JavaScript files.loaderDoNothingToJs: {
test: /\.js$/i,
exclude: /node_modules|_guides|guides/,
type: 'javascript/auto'
},
loaderCompileCoffee
This loader process coffee files by translating them to JS.loaderCompileCoffee: {
test: /\.coffee$/i,
exclude: /node_modules/,
type: 'javascript/auto',
use: [
{
loader: 'coffee-loader',
options: {
transpile:{
presets: [
'@babel/preset-env'
]
}
}
}
],
},
copyImages
This loader will look at all the images, fonts, etc. in the HTML source filescopyImages: {
test: /\.(jpe?g|png|gif|svg|ico|ttf|eot|woff|woff2)$/i,
exclude: /node_modules/,
type: 'asset/resource',
generator: {
filename: '[name][ext]'
}
}
loadHTMLAndReplaceMateriaScripts (Required)
This loader replaces any materia scripts such as `materia.creatorcore.js` and `materia.enginecore.js` with the ones used by MWDK.loadHTMLAndReplaceMateriaScripts: {
test: /\.html$/i,
exclude: /node_modules|_guides|guides/,
type: 'asset/source',
use: [
{
loader: 'string-replace-loader',
options: { multiple: materiaJSReplacements }
},
]
},
loadAndPrefixSASS
This loader will process any SASS/SCSS/CSS files and comes with an autoprefixer which adds any necessary vendor prefixes.loadAndPrefixSASS: {
test: /\.s(a|c)ss|css$/i,
exclude: /node_modules\/(?!(materia-widget-development-kit\/templates)\/).*/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: "css-loader",
options: {
url: false,
esModule: false
},
},
{
// postcss-loader is needed to run autoprefixer
loader: 'postcss-loader',
options: {
postcssOptions: {
// add autoprefixer, tell it what to prefix
plugins: [
require('autoprefixer')({
overrideBrowserslist: browserList
})
],
}
},
},
"sass-loader",
],
}
Next, create the options
object that we will pass to the MWDK with the entries, copy list, and rules we defined.
let options = {
entries,
copyList,
moduleRules
}
Finally, steal borrow the webpack config from the MWDK, and pass it the options object we created. Then, expose the config as a module for MWDK to grab and use!
const widgetWebpack = require('materia-widget-development-kit/webpack-widget')
let buildConfig = widgetWebpack.getLegacyWidgetBuildConfig(options)
module.exports = buildConfig
Run yarn start
in the widget's root directory. The widget will be hosted at localhost:8118 by default.
To change the port, you must update process.env.PORT
:
- Run
export PORT=1234
- Run
yarn start
as usual
The default node environment is development. If you wish to change this to production, you may set process.env.NODE_ENV
in a similar fashion:
- Run
export NODE_ENV=production
- Run
yarn start
as usual
Use the Download Package option on either the Player or Creator page to either download a compiled .wigt
file locally (it's just a .zip file, but renamed) or install directly to your local instance of Materia. This requires a currently running local instance of Materia in Docker.
Visit the Developing Materia Widgets section of our docs site for comprehensive documentation related to authoring a widget.
Visit our page detailing the changes required to implement MWDK v3.x in your widget.
As of MWDK v3.0.0, you can access your widget using the same urls as Materia.
Creator: /mwdk/widgets/1-mwdk/create
Player: /mwdk/player/