pyro / webpack
Provides the tools and logic to build a modern and modular frontend application for the PyroCMS admin control panel
Installs: 162
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 2
Forks: 0
Open Issues: 0
Language:TypeScript
Requires
- laradic/support: ~2.0
- ocramius/generated-hydrator: 3.0.*
This package is auto-updated.
Last update: 2024-12-14 18:24:22 UTC
README
This package provides the tools and logic to build a modular frontend application for the PyroCMS admin control panel.
This package does not provide a frontend application. This package does not change anything PyroCMS is doing
Features
- Create modular javascript for addons (which are already modular).
- Addons can enable javascript module(s) at any given point.
- Uses
yarn workspaces
(providesyarn
with somewhat similar functionality as thecomposer-merge-plugin
does withcomposer
) - Utilizes the (great) things webpack provides
- Tree shaking
- Dynamic imports (async loading)
- HOT reloading
Basic Example
-
Lets pretend to have a module addons/shared/pyro/core-module that contains
-
lib/index.js
export class Application { static getInstance(){return new Application()} register(provider){} boot(){} bind(){} make(){} } export class ServiceProvider { app = Application.getInstance() } export class CoreModuleServiceProvider extends ServiceProvider{ register(){} }
-
lib/__variables.scss
@use "~bootstrap/scss/variables" with ( $text-color: blue; ) $core-variable-one: #333 !default; $core-variable-two: darken($core-variable-one, 5) !default;
-
src/CoreModuleServiceProvider.php
class CoreModuleServiceProvider extends \Anomaly\Streams\Platform\Addon\AddonServiceProvider { public function boot(Webpack $webpack){ $webpack->enableEntry('@pyro/core-module'); } }
-
-
Lets pretend to have another module addons/shared/pyro/foo-module that contains
-
lib/index.js
import './style.scss'; import {ServiceProvider} from '@pyro/core-module' export function logWithPrefix(string){ console.log('prefix', string) } export class FooService { hello(){ logWithPrefix('FooService hello') } } export class FooModuleServiceProvider extends ServiceProvider{ register(){ logWithPrefix('registered FooModuleServiceProvider') this.app.bind('foo.service', FooService); } }
-
lib/style.scss-
@import "@pyro/core-module/lib/variables"; .foo-module { &__item { color: $core-variable-one; &--disabled { color: $core-variable-two; } } }
-
src/FooModuleServiceProvider.php
class FooModuleServiceProvider extends \Anomaly\Streams\Platform\Addon\AddonServiceProvider { public function boot(Webpack $webpack){ $webpack->enableEntry('@pyro/foo-module'); // can obviously be called anywhere, like controllers actions, route-groups etc } }
-
-
Lets pretend to have another module addons/shared/pyro/bar-module that contains
-
lib/index.js
import {ServiceProvider} from '@pyro/core-module' import {FooService} from '@pyro/foo-module'; // can import from other modules export class BarModuleServiceProvider extends ServiceProvider{ register(){ logWithPrefix('registered BarModuleServiceProvider') } boot(){ const fooService:FooService = this.app.make('foo.service'); fooService.hello(); } async loadStyle(){ return import('./style.scss') } }
-
lib/style.scss
$core-variable-one: #999; @import "@pyro/core-module/lib/variables"; .bar-module { &__item { color: $core-variable-one; &--disabled { color: $core-variable-two; } } }
-
src/BarModuleServiceProvider.php
class BarModuleServiceProvider extends \Anomaly\Streams\Platform\Addon\AddonServiceProvider { public function boot(Webpack $webpack){ $webpack->enableEntry('@pyro/bar-module'); } }
-
-
Which we can combine and bootstrap in a view
Like addons/shared/pyro/core-module/resources/view/frontend__application.twig And pretend we called
ViewIncludes->include('cp_scripts', 'pyro.module.core::frontend__application')
inCoreModuleServiceProvider::boot
{% import "webpack::include_webpack" %} <script> // The namespace is set in webpack.php config (or .env WEBPACK_NAMESPACE) var exported = window['$NAMESPACE$']; exported.providers; // array of ServiceProvider classes of enabled entries. var app = exported.pyro__core_module.Application.getInstance() // or var app = exported['@pyro/core-module'].Application.getInstance() exported.providers.forEach(function(ProviderClass){ app.register(ProviderClass); }) app.boot().then(function(){ var fooService = app.make('foo.service'); fooService.hello() // app.$mount() ??? // app.render() ??? // implement it yourself }) </script>
5Run yarn serve
, yarn build:dev
or yarn build:prod
**`yarn serve`** Will start a webpack-dev-server. `Pyro\Webpack` is aware of this will render the webpack-dev-server asset paths.
This will enable HOT Reloading on the scss files we defined. (Vue or React can easily be added with HMR aswell, and is explained further onwards)
**`yarn build:prod`** Will create production assets and place them by default in the `public/assets` (configurable). Again `Pyro\Webpack` is aware of this and will render the production asset paths.
Installation
-
composer.json
"pyro/webpack": "^1.0"
-
app.php
Pyro\Webpack\WebpackServiceProvider::class;
-
.env
WEBPACK_ENABLED=true WEBPACK_NAMESPACE=pyro WEBPACK_OUTPUT_PATH=public/assets WEBPACK_PROTOCOL=http WEBPACK_HOST=localhost WEBPACK_PORT=8079 WEBPACK_PATH=storage/webpack.json
-
package.json
{ "workspaces": { "packages": [ "addons/shared/*/*", "core/*/*", "vendor/pyro/webpack" ] }, "scripts": { "build:dev": "NODE_ENV=development webpack --config webpack.config.js", "build:prod": "rm -rf public/assets && NODE_ENV=production webpack --production --config webpack.config.js", "serve": "NODE_ENV=development webpack-dev-server --inline --hot --config webpack.config.js" }, "dependencies": { "@pyro/webpack": "^1.0.0", "@radic/webpacker": "^7.2.0", "webpack": "^4.40.2", "webpack-cli": "^3.3.8", "webpack-dev-server": "^3.8.0" } }
-
webpack.config.js
import { PyroBuilder } from '@pyro/webpack'; const builder = new PyroBuilder({ globs : [ 'addons/shared/*/*', 'addons/*/*', 'core/*/*' ], rootPath : __dirname }) const { wp, env, addons } = builder.init(); // any custom logic const config = wp.toConfig(); export default config;
-
Create a view like shown at Basic Example > 4: Create a view to..
Add a addon to the builder
In order to get a addon included in the builder, a few additional steps are required.
- Ensure the addon has a
package.json
(next to the composer.json file) - It's recommended to set the
name
field in package.json the same as in composer.json, but prefixed with an@
. - Ensure package.json has a the
version
field, preferably1.0.0
. This version should not be changed. - Add the
pyro
configuration. Check the example below
Example of a valid package.json:
{ "name": "@pyro/foo-module", "version": "1.0.0", "scripts": {}, "main": "lib/index.js", "typings": "lib/index.js", "types": "lib/index.js", "pyro": { "srcPath": "lib", "entrypoints": [ {"path": "index.js", "provider": "FooModuleServiceProvider"} ] }, "dependencies": { "@pyro/core-module": "^1.0.0", "bootstrap": "^4.3.1", "element-ui": "^2.12.0", "font-awesome": "^4.7.0", "vue-clickaway": "^2.2.2" }, "devDependencies": {} }
PHP Pyro\Webpack
Pyro\Webpack\Webpack
enableEntry($name, $suffix = null)
JS @pyro/webpack
webpack-chain
Provides the chaining webpack configurator API to generate and simplify the modification of webpack@radic/webpacker
Extends the chaining API with various useful features. Additionally it also provides a whole range of pre-configured, but reconfigurable presets. This aims to make your webpack config small and to the point.@pyro/webpack
ProvidesPyroBuilder
to setup webpack. It locates all PyroCMS javascript addon modules and adds them correctly to the webpack configuration.
import { PyroBuilder } from '@pyro/webpack'; const builder = new PyroBuilder({ globs : [ 'addons/shared/*/*', 'addons/*/*', 'core/*/*' ], rootPath : __dirname }) // init() // 1: will find and register all found addons // 2: setup webpack configuration, including addons // 3: returns the Webpacker (webpack-chain) and addon instances array const { wp, env, addons } = builder.init(); // At this point you can use 'wp' (Webpacker/webpack-chain) to add or alter any configuration made // change the output dir? wp.output.path('public/some-other-dir'); // add postcss loader before sass loader in the sass loader use array? wp.module.rule('scss') .use('postcss-loader') .loader('postcss-loader') .before('sass-loader') .options({ preserve : true, whitespace: false }) // modify module rule options? wp.module.rule('babel').use('babel-loader').tap(options => { options.plugins.push(['someplugin']) return options }) // Webpacker also comes with some extra features. // Example: to use @import "~accelerant-theme/.." in SCSS instead of relative paths. wp.ensureLink(path('core/pyrocms/accelerant-theme'), path('node_modules/accelerant-theme')); // At the end of the script transform into a webpack configuration object and export it const config = wp.toConfig(); export default config;