Back to top

添加新评论

One approach to implement the progressive decoupled Drupal 8

There are a lot of discussion online addressing the benefit of a progressive decoupled Drupal. You can read more at Should we decouple Drupal with a client-side framework? I have been thinking about how to implement this new feature for Drupal. Today, I am going to take a front-end theming approach, and write down my ideas of steps and iterations for the actual implementation below:

Before I start proposing the actual change, I'd like to review some background information or where we are:

a. For any page served by Drupal, we can think it is produced by a list of nested templates, in Drupal 8, which are in twig formats. Below is an over simplified example:

<...>
  <header>
    <logo></logo><menu.html.twig></menu.html.twig>
  </header>
  <content>
    <breadcrumb.html.twig></breadcrumb.html.twig>
    <views-view.html.twig>
      <views-view-grid.html.twig>
        <...>
          <views-view-field.html.twig></views-view-field.html.twig>
        </...>
      </views-view-grid.html.twig>
    </views-view.html.twig>

    <views-view.html.twig>
      <views-view-list.html.twig>
        <...>
          <views-view-field.html.twig></views-view-field.html.twig>
        </views-view-list.html.twig>
      </...>
    </views-view.html.twig>
  </content>

</...>

b. It's not trivial to realize that one can actually override any of these twig templates to theme the values in JSON format. If all the templates are overridden this way, then for any page served by Drupal, we will see the values in the above example markup presented with JSON format. Furthermore, we should be able to automate this overriding process for some or all templates.

If we keep these two facts in mind, we shall continue to the implementation plan:

Iteration 1: Working Model
The user story for the progressive decoupling feature can be seen as: When a user first requests the site, the landing page is fully assembled and served by Drupal, but when a user performs an action on the site to request a second "page" (such as clicking a link), Ajax call is fired instead and it retrieves only necessary changes from the site. These necessary changes include both a. Content/Value change and/or b. HTML markup change.

Step 1: Obviously, Drupal can serve the first page well, but the first change we need is to make Drupal to keep track of all the twig templates used on the first page and embody this list in the HTML and send it over to the client.

Step 2: Client-side hijacks all the links or form-send-actions, so when these actions occur, the client-side will do it via Ajax.

Step 3: When an Ajax call is fired, it also concatenates the list of templates' names. So, the actual call would look like this:

http(s)://example.com/blog/blog-title-clean-url?templates=page,panels,menu,breadcrumb,views-view-grid,views-view-field,views-view-list,...,...

Step 4: When Drupal receives a request with special parameter like "?templates=", it shall recursively use the overridden (theme the values in JSON) templates defined in b., if the to-work-on-template is on the list sent from the client; otherwise shall use the default template. The result page should be mixed with content wrapped in JSON and content wrapped in normal HTML. Drupal sends the page back to the client.

Step 5: When the client Ajax callback fires, the client-end UI recursively traverse the result page. The UI will refill or replace the values if in JSON format, otherwise, it will replace or append an entire HTML part from the result. The UI will also handle other related changes, for example, update the current URL in the address bar.

For this to work, it's necessary to turn all CSS and JS aggregation. In other words, all CSS and JS are sent at the first page request.

Iteration 2: Improvement

In many cases, when user navigates from one page to another, a lot of page elements are unchanged, for example: Main Navigation, Footer or Sidebar. Therefore, we can speed up the Step 4 even further. Drupal 8 implemented cache tags. So, in Step 4, when Drupal traverses down the templates list, it can check the cache tags for the specific template (Need to find how feasible this is.), and decides if it needs reproduction or simply uses the cached version.

Step 6: If a template it's cached, then don't even send it or send small signal. The client needs to handle the void or signal.

Iteration 3: Ubiquitous with Web Components

Step 7: If Drupal outputs a template with HTML markup, then let it meet the custom element specification of Web Components. The resulting effect is that any template served by Drupal can be "HTML Import" even by the rest of the Web. For example, one external web page can "HTML Import" a slideshow from a nice blog post on Drupal by requesting a URL like this

http(s)://example.com/blog/blog-title-clean-url?element=views-view-slideshow

The above idea is brief, but the actual implementation is quite a lot of work. However, I consider this approach is the most doable one by far. Please feel free to ask questions or make suggestions below.