I should have written an introduction, but I saw other articles that were well written, so I just wrote about some of the problems I encountered in them.

See this article at the end of installing single-SPA.

background

A little background

The reason why we use single-SPA is because the company needs to dismantle the project. At this time, we need to know the concept of micro front end and what is a micro front end.

Microfront-end service

The microfront-end architecture is a kind of architecture similar to microservices, which was proposed by ThoughtWorks in 2016. It applies the concept of microservices to the browser side, transforming a Web application from a single single application into an aggregation of several small front-end applications.

The change is that these front-end applications can be independently run, independently developed, and independently deployed.

In the project, single-SPA was used to build the micro-front-end framework. Before building the framework, we need to know two knowledge points, namely, single-SPA and ImportMap.

single-spa

Single-spa is a JavaScript front-end solution for front-end microservitization.

Features:

  • Use multiple technology frameworks (React, Vue, AngularJS, Angular, Ember, etc.) on the same page without refreshing the page.
  • (No refactoring of existing code) Write code using a new technical framework that does not require refactoring of code in existing projects.
  • (Better performance) The code for each individual module can be loaded on demand without wasting additional resources. Each independent module can run independently.

importmap

Let’s start with two pieces of code

import moment from 'moment';
import 'http://momentjs.com/downloads/moment.js';
Copy the code

When we write the above code in a file, it is obvious that the first line will not work properly and the second line will work properly, but if we want the first line to work properly, the importMap will come into play. Just write the following in an HTML file:

<script type="importmap">
    {
        "imports": {
            "moment": "https://momentjs.com/downloads/moment.js",}}</script>
Copy the code

That’s it.

However, browsers don’t support it right now, so if you want to support it, you need to introduce System.js.


<script type="systemjs-importmap">
    {
        "imports": {
            "moment": "https://momentjs.com/downloads/moment.js",}}</script>
<script src="https://cdn.jsdelivr.net/npm/systemjs/dist/system.js"></script>

Copy the code

In single-SPA, we need to import all module files and subprojects in the root project with importMap so that module references can be made in the rest of the project. As mentioned above, you can think of moment as a subproject.

Single-spa is used to package projects as reference modules.

You can look at this project, which is an example of what the author wrote about single-SPA.

And root-config is its root project, which you can start here.

For more information, see the video posted by @Joel Denning at 🔬.

Problems encountered

How to open importMap plug-in

Enter in the browser’s console

localStorage.setItem(‘devtools’, true);

And this little cutie showed up.

Subproject packaging

In the component reference of microservices, files need to be packaged into a single JS file due to the introduction of CDN. Vue-cli3-service (node_modules/_@[email protected]@@vue/cli-service/lib/config) has some built-in Webpack configuration. In the sub-project packaging process, we need to turn some configuration off and package it into a file that supports system.js. We need to do the following:

  • Package the project into a file that you can import
  • Remove the configuration of code splitting (code splitting is generatedchunk-vendorsFile)
  • Get rid ofmini-css-extract-plugin(The plug-in will link the componentscssPull it out)

The following code

> vue.config.js

process.env.VUE_CLI_CSS_SHADOW_MODE = true; // Remove the configuration that separates CSS from JS

module.exports = {
    chainWebpack: config= > {
        config.optimization.delete('splitChunks') // Turn off code splitting
        config.output
            .filename('app.js')
            .library('@[library]/[sub-project]')
            .libraryTarget('amd') // Packing method
            .end()
    }
    ...
}
Copy the code

But it’s all bullshit… In fact, these things can be solved as long as a plug-in, the original author wrote vuE-cli-plugin-single-spa plug-in, directly installed.

npm install vue-cli-plugin-single-spa -D

❗️❗️ it is also important that subprojects do not load routes on demand (const [component] = () => import([router]);) (Import [Component] from [Router]), otherwise it will be packaged into different chunks and cannot be properly loadedroot-configIntroduction.

The file path of the subproject is 404

After the packaging process above, the packaged file is /dist/js/app.js. In the plug-in written by the original author, the rewritten file path is as follows:

That’s it.

If it is 404, the project may have been packed to a different path, and you need to open the TAB for the subproject to see the file address in your browser.

The element-UI icon is not displayed

Note that vue-cli-plugin-single-spa does not handle static resources such as text, so although NPM run build does not show static resources packaged as separate files, they are in fact packaged as static files. The best way to solve this problem is to convert element-UI to CDN import rather than node_module import.

Render wrong item

It was clearly pointing to item A, but rendered as item B.

The file path configured in the plug-in is wrong. Port 8080 May be configured as port 8081 in project A, which is especially prone to this problem in multi-project development.

How to achieve two column layout right can switch items

I was naive enough to think that I could import the subproject as a router component, but that was not possible. The project is too coupled to be packaged as a component depending on individual plug-ins. So it’s essentially two DOM nodes side by side. But we can achieve a fake effect.

In the Menu bar router,

{
    path: '/',
    component: Home,
    name: 'home',
    redirect: '/sub-project',
    children: [{
      path: 'sub-project/*',
      name: 'sub-project',}},Copy the code

If the sub-project has some router conversions, the navbar will not match properly if the sub-project has some router conversions.

Setting is required in order to match the corresponding router in the subproject

base: ‘sub-project’

Then set the float in the menu bar, the corresponding width of the right margin is ok.

More and more

Implementing a single-SPA front-end microservices from 0 to Single-SPA Vue-Microfrontends to build single-page applications like these are the problems I have encountered. Give me a small upvote if you like. Thank you