lightsource/front-blocks 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

lightsource/front-blocks

Composer 安装命令:

composer require lightsource/front-blocks

包简介

This package helps combine front-end resources (html, js, css) into reusable blocks (modules)

README 文档

README

What is it?

This package helps combine front-end resources (HTML, CSS, JS) into reusable blocks (modules).

1. Advantages
2. How to use
3. Block
4. Requirements
5. Examples of usage
6. Advanced
7. Extra loading

Advantages

  • Allows keep all resources grouped, that simplify editing and improving code reading
  • Supports dependencies between blocks, allows to use a block within another block, provides used block resources (CSS, JS) in the right order
  • Uses Twig as a template engine, friendly to scss and webpack (see Examples of usage)
  • Extra loading of the package is insignificant. See Extra loading for details
  • Blocks can be placed in different folders (e.g. WordPress parent and child theme)

How to use

  1. Install the composer package

composer require lightsource/front-blocks

  1. Create a FrontBlocks instance
use LightSource\FrontBlocks\FrontBlocks;
use LightSource\FrontBlocks\Settings;
use LightSource\FrontBlocks\ExternalDependencies;

$settings = new Settings();
// namespace & folder of your blocks
$settings->addBlocksFolder('MyNamespace', 'AbsPathToMyFolder');
// optionally, your psr/container implementation for extra dependencies, see more information about this feature below
$container = null;
// optionally, your PSR-3 compatible logger, will be used when a twig template has syntax errors
$logger               = null;

$frontBlocks = new FrontBlocks($settings, $container, $logger);   
  1. Create blocks
/Blocks
    Homepage
        Homepage.twig
        Homepage.css
        Homepage.php          

Homepage.php

// your block should extend the Block class
// (or implement \LightSource\FrontBlocks\Interfaces\BlockInterface, but only in case you need your own implementation)
class Homepage extends \LightSource\FrontBlocks\Block\Block
{
    protected string $title;

    public function loadById(int $id)
    {
        parent::load();

        // todo
        $this->title = 'Some title';
    }
}

Homepage.twig


<div class="homepage">{{ title }}</div>
  1. Render blocks, get used resources
// Block's creation with :
// a) automatic initialization of class's protected fields (for fields with built-in types or with the Block type)
// b) automatic passing external objects to block's constructors (where it needs)
$homepage = $frontBlocks->getCreator()->create(Homepage::class);
$homepage->loadById(1);

// rendering a target twig template with arguments (from the class's protected fields)
echo $frontBlocks->getRenderer()->render($homepage);

// reading & combining resources from used blocks by an extension (in the right order of rendering and with dependencies)
echo '<style>';
echo $frontBlocks->getRenderer()->getUsedResources('.css');
echo '</style>';

See Examples of usage to get more info.

Block

Block it's a PHP class and resources near the class file.

  • Static resources
    Files like : template (.twig), CSS (.css, .scss, .min.css), JS (js, min.js), images (.png) and such...

  • Block class - provides data for a twig template, manages dependencies

    • All protected fields will be used as arguments to a twig template.
    • Protected fields can be fields with built-in types (string, int, array...) and other Blocks, if these fields have declared types then they will be auto initialized with a default value (include Block fields, so it'll automatically create an instance of a declared class)
    • All protected fields with a Block type will be marker as dependencies of this block
    • Can have a parent-children relation (so each block can be extended)

Requirements

  • php 7.4+
  • Blocks should have a PSR-4 compatible namespace with an autoloader
  • Resource name should be the same as a Block name
  • Using the BEM methodology isn't required but highly recommended

Examples of usage

  1. Example 1 - without scss & webpack
  2. Example 2 - with scss & webpack

Advanced

1. Loader

Package has the loader class, it gets a list of block classes and calls static setup(?ContainerInterface $container) method for every instance. Very useful if you want to add some listeners for every block, or do another job. E.g. in WordPress you can setup ajax listeners for every block.

$frontBlocks->getLoader()->loadAllBlocks();

2. External dependencies (during auto-creation)

There is automatically creation of inner blocks, it means they should have a constructor without any arguments, but sometimes you may need extra dependencies, like logger or anything else. In such cases the external dependencies feature will help. The FrontBlocks class has the psr/ContainerInterface argument, you can provide any implementation here (e.g. php-di) and then during automatic creation the container will be asked for every constructor's argument, and his response will be automatically passed to the constructor (comparing by types, its possible thanks to PHP reflection opportunities, so order or names of dependencies are not important here).

Block

class MyBlock extends \LightSource\FrontBlocks\Block\Block
{
    private MyExtraClass $myExtraClass;

    // you can have any amount of dependencies, order is not important together with variable names
    // external dependencies are unique per block, so one block can have dependencies, others may not have
    public function __construct(MyExtraClass $variableWithAnyName)
    {
        parent::__construct();
        $this->myExtraClass = $variableWithAnyName;
    }
}

then pass your dependency to your container

$dependency = new MyExtraClass();
// in this sample the php-di\php-di package is being using
$container = new \DI\Container();
$container->set(MyExtraClass::class, $dependency);
$frontBlocks = new FrontBlocks($settings, $container);

3. Twig template

  • additional keys (_template, _isLoaded, _parentTemplate for each block are available (_isLoaded will be true after the load() method call in a related Block)
  • _merge filter (merging arrays recursively unlike of the standard merge)
  • _include function (blockArgs,additionalArgs) which uses the additional key for blocks include, so you can include blocks like it {{ _include(blockName,{classes:['block-name',]} ) and it'll locate a template by the '_template' field and will render only if '_isLoaded' is set
  • to extend a twig template (obviously php block class should extend a parent) - use the ordinary twig way with the pre-defined _parentTemplate variable, so {% extends _parentTemplate %}

4. Array of blocks

Fields with an array of blocks - are also supported, in the same way as the block fields, so getTemplateArgs() will be automatically called for every item during rendering, it means you can have for in a twig template with _include() for every item without extra steps from your side.

5. Tool for copy blocks

Tool for copy blocks (with names replacing) is available
E.g. in the Blocks folder the command
{pathToComposer}/vendor/bin/fbf copy Source/Source.php Target/Target.php
will copy the Block and all siblings files and will do name replacing, so you can create an example block and reproduce new blocks from it.

6. Polymorphism

PHP (7.4) doesn't support polymorphism in fields directly, so unfortunately you can't do something like it:

class Element {

}
class ElementThemeOrange extends Element {
 
}
class Wrapper {
 protected Element $element;
}
class WrapperThemeOrange extends Wrapper {
 protected ElementThemeOrange $element;
}

BUT the package supports a trick below:

class Element {

}
class ElementThemeOrange extends Element {
 
}
class Wrapper {
 protected Element $element;
}
class WrapperThemeOrange extends Wrapper {
 public function __construct() {
  parent::__construct();
  
  $this->element = new ElementThemeOrange();
 }
}

In this case when you use the creator ($wrapper = $frontBlocks->getCreator()->create(WrapperThemeOrange::class);) the package will pick up exactly the ElementThemeOrange class.
(Note: never rely on your initialization of inner blocks in a constructor, because this initialization will be used only to get a class name and then the field will be overridden with a new instance, that will be created using the creator, otherwise the External dependencies feature would be unavailable here. So neither set up any values nor call any methods in a constructor for inner blocks, it'll have no effect)

Extra loading

Extra loading exactly of the package is insignificant and more dependents of Twig. Below you can see rough values which were got on an instance with 4vCPU 16 RAM, SSD. End values will be others, depending on your instance and used blocks.

Auto-loading of 100 blocks (optional) : 9 milliseconds
Twig rendering of 100 blocks - 62 milliseconds
Combining resources of 100 blocks - 3 milliseconds

lightsource/front-blocks 适用场景与选型建议

lightsource/front-blocks 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 465 次下载、GitHub Stars 达 1, 最近一次更新时间为 2021 年 05 月 19 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「reusable blocks」 「front-end blocks」 「reusable modules」 「front-end modules」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 lightsource/front-blocks 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 lightsource/front-blocks 我们能提供哪些服务?
定制开发 / 二次开发

基于 lightsource/front-blocks 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 465
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 6
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: GPL-2.0-only
  • 更新时间: 2021-05-19