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
(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.
We can see that the reported error
officially our'replace' error, click on the main
compressed file.
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:
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.
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:
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.
Six: vscode workspace settings
These are the two setting items in the picture:
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.
Becomes so big:
We change back to 12
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:
The content of the package file index.js
export default () => {
console.log("我是本地的包");
};
Add configuration in package.json
file:
points to local
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.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。