写点什么

自建开发工具系列 -Webkit 内存动量监控 UI(七)

用户头像
Tim
关注
发布于: 3 小时前
自建开发工具系列-Webkit内存动量监控UI(七)

本次修改集中在调整原来的编译结构,将新建 demo 目录,把 create-react-app 的配置重新调整。然后把工具直接编译成单个 js 文件,便于在一些特殊场合下使用。


执行 npm run eject 命令,让配置回到 webpack.config


tim@Tim tools-webkit-memory % npm run eject
> tools-webkit-memory@0.1.1 eject /Users/tim/Documents/platform/tools-webkit-memory> react-scripts eject
NOTE: Create React App 2+ supports TypeScript, Sass, CSS Modules and more without ejecting: https://reactjs.org/blog/2018/10/01/create-react-app-v2.html
✔ Are you sure you want to eject? This action is permanent. … yesEjecting...
Copying files into /Users/tim/Documents/platform/tools-webkit-memory Adding /config/env.js to the project Adding /config/getHttpsConfig.js to the project Adding /config/modules.js to the project Adding /config/paths.js to the project Adding /config/pnpTs.js to the project Adding /config/webpack.config.js to the project Adding /config/webpackDevServer.config.js to the project Adding /config/jest/babelTransform.js to the project Adding /config/jest/cssTransform.js to the project Adding /config/jest/fileTransform.js to the project Adding /scripts/build.js to the project Adding /scripts/start.js to the project Adding /scripts/test.js to the project
Updating the dependencies Removing react-scripts from dependencies Adding @babel/core to dependencies Adding @pmmmwh/react-refresh-webpack-plugin to dependencies Adding @svgr/webpack to dependencies Adding @typescript-eslint/eslint-plugin to dependencies Adding @typescript-eslint/parser to dependencies Adding babel-eslint to dependencies Adding babel-jest to dependencies Adding babel-loader to dependencies Adding babel-plugin-named-asset-import to dependencies Adding babel-preset-react-app to dependencies Adding bfj to dependencies Adding camelcase to dependencies Adding case-sensitive-paths-webpack-plugin to dependencies Adding css-loader to dependencies Adding dotenv to dependencies Adding dotenv-expand to dependencies Adding eslint to dependencies Adding eslint-config-react-app to dependencies Adding eslint-plugin-flowtype to dependencies Adding eslint-plugin-import to dependencies Adding eslint-plugin-jest to dependencies Adding eslint-plugin-jsx-a11y to dependencies Adding eslint-plugin-react to dependencies Adding eslint-plugin-react-hooks to dependencies Adding eslint-plugin-testing-library to dependencies Adding eslint-webpack-plugin to dependencies Adding file-loader to dependencies Adding fs-extra to dependencies Adding html-webpack-plugin to dependencies Adding identity-obj-proxy to dependencies Adding jest to dependencies Adding jest-circus to dependencies Adding jest-resolve to dependencies Adding jest-watch-typeahead to dependencies Adding mini-css-extract-plugin to dependencies Adding optimize-css-assets-webpack-plugin to dependencies Adding pnp-webpack-plugin to dependencies Adding postcss-flexbugs-fixes to dependencies Adding postcss-loader to dependencies Adding postcss-normalize to dependencies Adding postcss-preset-env to dependencies Adding postcss-safe-parser to dependencies Adding prompts to dependencies Adding react-app-polyfill to dependencies Adding react-dev-utils to dependencies Adding react-refresh to dependencies Adding resolve to dependencies Adding resolve-url-loader to dependencies Adding sass-loader to dependencies Adding semver to dependencies Adding style-loader to dependencies Adding terser-webpack-plugin to dependencies Adding ts-pnp to dependencies Adding url-loader to dependencies Adding webpack to dependencies Adding webpack-dev-server to dependencies Adding webpack-manifest-plugin to dependencies Adding workbox-webpack-plugin to dependencies
Updating the scripts Replacing "react-scripts start" with "node scripts/start.js" Replacing "react-scripts build" with "node scripts/build.js" Replacing "react-scripts test" with "node scripts/test.js"
Configuring package.json Adding Jest configuration Adding Babel preset
Running yarn...yarn install v1.22.4[1/4] 🔍 Resolving packages...[2/4] 🚚 Fetching packages...[3/4] 🔗 Linking dependencies...warning " > @testing-library/user-event@12.8.3" has unmet peer dependency "@testing-library/dom@>=7.21.4".[4/4] 🔨 Building fresh packages...success Saved lockfile.✨ Done in 18.99s.Ejected successfully!
Staged ejected files for commit.
Please consider sharing why you ejected in this survey: http://goo.gl/forms/Bi6CZjk1EqsdelXk1
tim@Tim tools-webkit-memory %
复制代码


然后把原来 src 下的 index.js 和 index.css 转移到和 src 平级的 demo 目录中,用来运行查看工具库的引用情况。


这个时候因为入口文件改变到了 src 以外的位置,需要调整 webpack 的设置,create-react-app 的路径设置在./config/paths.js 中,这里做了入口位置的调整:


diff --git a/config/paths.js b/config/paths.jsindex 4e3d30e..1b9b360 100644--- a/config/paths.js+++ b/config/paths.js@@ -57,9 +57,9 @@ module.exports = {   appBuild: resolveApp(buildPath),   appPublic: resolveApp('public'),   appHtml: resolveApp('public/index.html'),-  appIndexJs: resolveModule(resolveApp, 'src/index'),+  appIndexJs: resolveModule(resolveApp, 'demo/index'),   appPackageJson: resolveApp('package.json'),-  appSrc: resolveApp('src'),+  appSrc: resolveApp('/'),   appTsConfig: resolveApp('tsconfig.json'),   appJsConfig: resolveApp('jsconfig.json'),   yarnLockFile: resolveApp('yarn.lock'),
复制代码


这个时候发现其实让 webpack 跑起 devServer 来看工具就引用了好多库


然候调整一下 tsconfig 的编译配置,让 tsc 打出单个 js 文件供便捷加载


diff --git a/config/paths.js b/config/paths.jsindex 4e3d30e..1b9b360 100644--- a/config/paths.js+++ b/config/paths.js@@ -57,9 +57,9 @@ module.exports = {   appBuild: resolveApp(buildPath),   appPublic: resolveApp('public'),   appHtml: resolveApp('public/index.html'),-  appIndexJs: resolveModule(resolveApp, 'src/index'),+  appIndexJs: resolveModule(resolveApp, 'demo/index'),   appPackageJson: resolveApp('package.json'),-  appSrc: resolveApp('src'),+  appSrc: resolveApp('/'),   appTsConfig: resolveApp('tsconfig.json'),   appJsConfig: resolveApp('jsconfig.json'),   yarnLockFile: resolveApp('yarn.lock'),diff --git a/tsconfig.json b/tsconfig.jsonindex 24cbf02..fef3d99 100644--- a/tsconfig.json+++ b/tsconfig.json@@ -1,7 +1,7 @@ {   "compilerOptions": {     "target": "es5", -    "module": "AMD", +    "module": "CommonJS",      "lib": ["DOM", "ES2015"],     "allowJs": true,      "declaration": true, @@ -9,11 +9,10 @@     "outFile": "./script/TWM.js",       "rootDir": "./src",     "strict": true, -    // "esModuleInterop": true,+    "esModuleInterop": true,     "jsx": "react-jsx"   },-  "include": [-    "src/**/*.tsx",-    "src/**/*.ts"+  "files": [   // 指定待编译文件+    "./src/App.tsx"     ] }
复制代码


现在就可以看到输出了 TWM.js 文件,包含代码的内容:


var __extends = (this && this.__extends) || (function () {    var extendStatics = function (d, b) {        extendStatics = Object.setPrototypeOf ||            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };        return extendStatics(d, b);    };    return function (d, b) {        if (typeof b !== "function" && b !== null)            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");        extendStatics(d, b);        function __() { this.constructor = d; }        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());    };})();define("config/api", ["require", "exports"], function (require, exports) {    "use strict";    Object.defineProperty(exports, "__esModule", { value: true });});define("utils", ["require", "exports"], function (require, exports) {    "use strict";    Object.defineProperty(exports, "__esModule", { value: true });    var displayPanel = function () {        var memoryBottom = 100;        var memoryTop = 0;        var TOOLS_HEIGHT = 30;        var MemoryLimitValue = TOOLS_HEIGHT;        var toolsDom = document.createElement('div');        toolsDom.id = 'twm';        toolsDom.className = 'tools';        toolsDom.style.cssText = 'width:130;height:48px;opacity:0.9;cursor:pointer;overflow:hidden;z-index:10000;will-change:transform;';        var panel = document.createElement('div');        panel.id = 'ms';        panel.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:black;';        toolsDom.appendChild(panel);        var noticeLabel = document.createElement('div');        noticeLabel.id = 'noticeLabel';        noticeLabel.style.cssText = 'color:white;font-family:Arial;font-size:9px;font-weight:bold;line-height:15px';        noticeLabel.innerHTML = '';        panel.appendChild(noticeLabel);        var nodeUI = document.createElement('div');        nodeUI.id = 'nodeUI';        nodeUI.style.cssText = "position:relative;width:120px;height:" + TOOLS_HEIGHT + "px;background-color:lightyellow";        panel.appendChild(nodeUI);        // 刷新后增加新的内存值和GC状态        while (nodeUI.children.length < 120) {            var bar = document.createElement('span');            bar.style.cssText = "width:1px;height:" + TOOLS_HEIGHT + "px;float:left;background-color:black";            nodeUI.appendChild(bar);        }        var updateData = function (dom, height, color) {            var child = dom.appendChild(dom.firstChild);            child.style.height = height + "px";            if (color)                child.style.backgroundColor = color;        };        var refreshGraph = function (dom, oHFactor, hFactor) {            [].forEach.call(dom.children, function (c) {                var cHeight = Number(c.style.height.substring(0, c.style.height.length - 2));                // 转换到 MB                var newVal = TOOLS_HEIGHT - ((TOOLS_HEIGHT - cHeight) / oHFactor) * hFactor;                c.style.height = newVal + "px";            });        };        // 避免没有 window.(performance as any).memory 的浏览器崩溃        if (window.performance && !performance.memory) {            performance.memory = { usedJSHeapSize: 0, totalJSHeapSize: 0 };        }        var precision;        var i;        function bytesToMB(bytes) {            precision = Math.pow(10, 0);            i = Math.floor(Math.log(bytes) / Math.log(1024));            return Math.round((bytes * precision) / Math.pow(1024, i)) / precision + " MB";        }        var lastTime = Date.now();        var lastUsedHeap = performance.memory.usedJSHeapSize;        var delta = 0;        var color = 'black';        var ms = 0;        var mbValue = 0;        var factor = 0;        var newThreshold = 0;        return {            domElement: toolsDom,            update: function () {                // 每秒刷新                if (Date.now() - lastTime < 1000 / 1)                    return;                lastTime = Date.now();                delta = performance.memory.usedJSHeapSize - lastUsedHeap;                lastUsedHeap = performance.memory.usedJSHeapSize;                // GC 判定,如果是清空内存,则使用绿色标识                color = delta < 0 ? 'green' : 'black';                ms = lastUsedHeap;                memoryBottom = Math.min(memoryBottom, ms);                memoryTop = Math.max(memoryTop, ms);                noticeLabel.textContent = window.performance.memory.jsHeapSizeLimit ? "\u5185\u5B58\u4F7F\u7528:   " + bytesToMB(ms) : 'Only Webkit';                mbValue = ms / (1024 * 1024);                if (mbValue > MemoryLimitValue) {                    factor = (mbValue - (mbValue % TOOLS_HEIGHT)) / TOOLS_HEIGHT;                    newThreshold = TOOLS_HEIGHT * (factor + 1);                    refreshGraph(nodeUI, TOOLS_HEIGHT / MemoryLimitValue, TOOLS_HEIGHT / newThreshold);                    MemoryLimitValue = newThreshold;                }                updateData(nodeUI, TOOLS_HEIGHT - mbValue * (TOOLS_HEIGHT / MemoryLimitValue), color);            }        };    };    exports.default = displayPanel;});define("App", ["require", "exports", "react/jsx-runtime", "react", "utils", "./App.css"], function (require, exports, jsx_runtime_1, React, utils_1) {    "use strict";    Object.defineProperty(exports, "__esModule", { value: true });    var TWM = /** @class */ (function (_super) {        __extends(TWM, _super);        function TWM(props) {            var _this = _super.call(this, props) || this;            _this.toolsNode = React.createRef();            _this.twm = utils_1.default();            return _this;        }        TWM.prototype.componentDidMount = function () {            var _this = this;            var updateLoop = function () {                if (_this.toolsNode.current.appendChild) {                    _this.toolsNode.current.appendChild(_this.twm.domElement);                }                if (_this.twm) {                    _this.twm.update();                }                if (window.performance.memory.jsHeapSizeLimit) {                    window.setTimeout(updateLoop, 1000);                }            };            window.setTimeout(updateLoop, 1000);        };        TWM.prototype.render = function () {            return (jsx_runtime_1.jsx("div", { style: { top: '0px', right: '0px', position: 'fixed' }, ref: this.toolsNode, className: "displayPanel" }, void 0));        };        return TWM;    }(React.Component));    exports.default = TWM;});
复制代码


发布于: 3 小时前阅读数: 5
用户头像

Tim

关注

还未添加个人签名 2018.05.01 加入

还未添加个人简介

评论

发布
暂无评论
自建开发工具系列-Webkit内存动量监控UI(七)