8

Issue 6: Sharing of nine front-end inspirations

This period

This series was originally called'Jiu Tiao Bug', but I have always felt that the name is not very appropriate. After thinking for a long time, I decided to change to Jiu Tiao Inspiration from this time (although the name is still bad). Most of the content to be shared this time is related to the project structure. Yes, let's take a look.

One: soucemap de-parses the packaged file

Our formal environment arranges compressed files. If the formal environment reports an error, how do we know exactly where the error occurred in the code? Maybe in some cases you need to perform soucemap de-analysis on the code, which requires mozila The official sourcemap reverse solution library, let's create a new file and try it out:

npx create-react-app my_inspire

We deliberately made an error, such as adding the following code to App.js

  function cc(str) {
    str.replace("-", ",");
  }

  cc();

Enter node_module/react-scripts/config/webpack.config.js do the following replacements:

// const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
const shouldUseSourceMap = true;

Run yarn build
image.png

(Key point) We take out the .map file separately and put it in a map folder. If this file is in the build folder, it will automatically help us do the soucemap parsing function.

image.png

We can see that the reported error officially our'replace' error, click on the main compressed file.

image.png

Remember these two parameters line = 1; and column = 241; .

Now we want to create a new project:

mikdir my_map
cd ./my_map
npm init -y
yarn add source-map
mikdir src
cd src
touch index.js

Add parsing code in index.js

const sourceMap = require("source-map");
const fs = require("fs");
let data = fs
  .readFileSync(process.cwd() + "/map/static/js/main.761f3095.chunk.js.map")
  .toString();

const consumer = new sourceMap.SourceMapConsumer(data);

consumer.then((code) => {
  const line = 1;
  const column = 241;
  const res = code.originalPositionFor({ line, column });

  console.log(
    code
      .sourceContentFor(res.source)
      .split("\n")
      .slice(Math.max(res.line - 5, 0), res.line + 5)
      .join("\n")
  );
});

.slice(Math.max(res.line - 5, 0), res.line + 5) take a look at this code 0616675eb206aa, here are the upper and lower 5 lines of code that print the error code at the same time.

You can get the following results by executing this file with the node command:

image.png

Two: sendBeacon sends data

For example, if we want to report the user's closing page operation, if we directly use axios report, the request will not be sent or cancelled by the browser. For example, the following method will make the uninstallation slower:

window.addEventListener('unload', logData, false);

function logData() {
    var client = new XMLHttpRequest();
    client.open("POST", "/log", false);
    client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
    client.send(analyticsData);
}

Looking at the code of the currently used burying point and monitoring library, they found that they will use sendBeacon api for data reporting. It can ensure that the data is delivered effectively and will not block the unloading or loading of the page. It is worth noting that this method is best only Passing a small amount of data should not be complicated to design, the usage is as follows:

window.addEventListener('unload', logData, false);

function logData() {
    navigator.sendBeacon("你的上报地址", "上报的数据");
}

Using the sendBeacon() method will make the user agent asynchronously send data to the server when it has the opportunity, without delaying the unloading of the page or affecting the loading performance of the next navigation. This solves all the problems when submitting analysis data: the data is reliable, the transmission is asynchronous, and the loading of the next page will not be affected.

image.png

Three: How to detect that the page is stuck and has no response

How to monitor the user's page crash? Because js is a single-threaded execution, if there is an infinite loop of page, then the code behind us cannot be executed, and of course the wrong monitoring code cannot be executed 🤔.

The idea is to jump out of single thread, Worker thread down the light of justice, Worker thread is a sub-thread that can be executed independently of the JS main thread, not affected by JS main thread, and we can pass Worker thread every 3 seconds Send a message to the JS main thread. If there is no reply from the main thread for more than 6 seconds, it can be considered that the main thread is stuck.

The following is a simplified version of monitoring:
image.png

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        var worker = new Worker('./worker.js');

        worker.onmessage = function (event) {
                console.log(`收到了子线程的问候: ${event.data}`)
                worker.postMessage('我很好!');
        }
    </script>
</body>
</html>

worker.js:

let come = 0;

const timer = setInterval(() => {
  waiting = true;
  come -= 1;
  self.postMessage("主线程你还好么?");

  if (come < -2) {
    navigator.sendBeacon("你的上报地址", "上报页面崩溃");
  }
}, 3000);

self.addEventListener(
  "message",
  function (e) {
    waiting = false;
    console.log(`收到了主线程的答复: ${e.data}`);
    come += 1;
  },
  false
);

Four: deep dependencies cannot be updated

For example, our main project depends A package & b package, A package is also dependent b package, when A package upgraded to rely when the latest version b package directly execute yarn command may cause us we The b package in the main project has been updated, but the a package
Although the package.json file has written "b":"*" but it may not be able to update to the latest version b , deleting the node_modules folder is also useless, because this bug is yarn.lock file, we need to yarn remove a and then restart yarn add a to solve the problem.

Five: yarn why

yarn why command is mainly used to show the reason why the package is needed, such as yarn add antd my project, but I did not install the dayjs library, then I execute the command:

yarn why dayjs
"antd#rc-picker" depends on it

antd is used by the date component in 0616675eb20bf5, and the size of the package will also be listed.

image.png

Six: vscode workspace settings

These are the two setting items in the picture:

image.png

The workspace refers to a folder opened with VS Code. A hidden folder named .vscode will be created under this folder, which contains the VS Code settings that only apply to the current directory. The workspace settings will be Override the user's setting, let's increase the font size.

image.png

Becomes so big:

image.png

image.png

We change back to 12

image.png

Use this function to format of 1616675eb20cc3 and the targeted configuration of a plug-in for a specific project.

Seven: react asynchronously introduce components @loadable/component

If the address of the imported file is dynamic, and his import path is /home/home1 or /home/home2 , the following writing will report an error:


const Home = () => import(`./home/home1`);

function App() {
  return (
    <div className="App">
      <p>app 页面</p>
      <Home></Home>
    </div>
  );
}

export default App;

Dynamically modify the import path with the help of plug-ins:

yarn add import @loadable/component
import "./App.css";
import loadable from "@loadable/component";

const n = 1;
const Home = loadable(() => import(`./home/home${n}`));


function App() {
  return (
    <div className="App">
      <p>app 页面</p>

      <Home></Home>
    </div>
  );
}

export default App;

This way at least two components need not be introduced.

Eight: package.json introduces the local package as a dependency

A reference to the introduction of the local package first thought is npm link & npm unlink brothers command, but when you introduced local package becomes much time will be a lot of trouble, such as when the release code also npm unlink , so much better now Projects all use lerna to do the project package management, I will have the opportunity to talk about lerna detail in the future.

Here I want to introduce another way, as shown below:

We have a package named @lulu/bao , create a new bao folder, put it in the project and need npm init to fill in the information completely:

image.png

The content of the package file index.js

export default () => {
  console.log("我是本地的包");
};

Add configuration in package.json file: points to local

image.png

It should be noted that, currently, npm install is required to take effect once, and it can be used in the following way.

import bao from "@lulu/bao";

bao();

Nine: The importance of ts in replacing the ui library

ts really important sometimes. Recently, I participated in an old project to replace the ui component library as a whole. I thought it was all different in style, but the result was full of pits.

For example, older versions of date components onchange event the second argument returns dayjs object format, but the new version of the component returns string all the processing method after, leading all wrong, this error ts can be very clear message come out.

The same is true for attribute replacement. For example, a new version of a component does not receive the style style attribute was passed in before is red. I need to think of other ways to style a bunch of 0616675eb20f91 to the component in other ways.

There is also a range of attribute values. button component previously had 4 attributes to choose from, but the new version only has two, which is really bald.

end

The ninth article talks about the problem of replacing ui components. In the next article, I will talk about more than 20 types of problems I encountered when replacing ui components for a large project. It is really eye-opening. This is the case this time, I hope Progress with you.


lulu_up
5.7k 声望6.9k 粉丝

自信自律, 终身学习, 创业者