现代前端工程化实践:高效构建的秘密
一、前端工程化错误监控
这种监控可以帮助开发人员及时发现和解决问题,提高应用程序的稳定性和可靠性。
1. Sentry:Sentry是一款开源的错误监控平台,可以监控前端、后端以及移动端应用程序中的错误和异常。Sentry提供了实时错误报告、错误分析和错误解决方案等功能。2. Bugsnag:Bugsnag是一款专门用于监控Web应用程序和移动应用程序的错误监控工具。它可以捕获JavaScript异常、网络请求错误、客户端错误等。3. Google Analytics:Google Analytics可以监控网站的访问量、页面浏览量、访问时长和用户行为等。它还提供了实时报告和错误报告等功能,可以帮助开发人员发现和解决问题。4. Performance API:Performance API是一个浏览器提供的API,可以监控Web应用程序的性能。它可以捕获页面加载时间、资源下载时间和JavaScript执行时间等信息。5. 前端错误监控SDK:很多前端错误监控工具都提供了JavaScript SDK,可以通过在应用程序中引入SDK来捕获错误和异常。开发人员可以根据捕获的错误信息来定位和解决问题。
二、项目构建
1、脚手架开局(已废弃⚠️)
全局安装create-react-app:
$ npm install -g create-react-app创建一个项目:
$ create-react-app your-app 注意命名方式Creating a new React app in /dir/your-app.如果不想全局安装,可以直接使用npx:
$ npx create-react-app your-app 也可以实现相同的效果
2、webpack开局(已废弃⚠️)
初始化项目空间
新建一个项目目录,在目录下执行:npm init -y
此时将会生成 package.json 文件
之后新建 src、config(配置webpack)文件夹,新建index.html文件
安装webpack和react相关依赖文件
npm i webpack webpack-cli webpack-dev-server html-webpack-plugin babel-loader path -D
npm i react react-dom
在src目录配置index.js文件
import React from 'react';
import ReactDOM from 'react-dom';ReactDOM.render(<React.StrictMode><div>你好,React-webpack5-template</div></React.StrictMode>,
document.getElementById('root')
);
在src目录配置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>react-app</title></head><body><div id="app"></div></body>
</html>
配置根目录webpack配置文件
新建webpack.common.js文件,部分代码仅供参考
const webpack = require('webpack');
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackObfuscator = require('webpack-obfuscator');
const pages = ['index' /*, "message", */]; // 多页面频道配置
const envConfig = require('./config/env');
const isProduction =process.env.APP_ENV === 'production' ||process.env.APP_ENV === 'preProduction';
const isDevelopment = process.env.APP_ENV === 'development';function recursiveIssuer(m) {if (m.issuer) {return recursiveIssuer(m.issuer);} else if (m.name) {return m.name;} else {return false;}
}// 获取CSS输出
function getCssOutput() {let pathStyle = {};pages.map((item) => {pathStyle[`${item}Styles`] = {name: item,test: (m, c, entry = item) =>m.constructor.name === 'CssModule' && recursiveIssuer(m) === entry,chunks: 'all',enforce: true,};});return pathStyle;
}/*** 【获取entry文件入口】* @returns {Object} 返回的entry { "static":"./src/static/index.js",}*/
function getEntry() {let entryConfig = {};pages.map((item) => {entryConfig[item] = `./src/${item}.js`;});return entryConfig;
}// 获取多个页面html生成配置
function getHtmlPlugin() {let plugins = [];pages.map((item) => {plugins.push(new HtmlWebpackPlugin({publicPath: envConfig.STATIC_DOMAIN, // 静态资源引入domaintemplate: `./src/${item}${isProduction ? '_prod' : ''}.html`,filename: `${item}.html`,hash: false,chunks: [item],// favicon: './favicon.ico',inject: true,minify: {collapseWhitespace: true, //把生成文件的内容的没用空格去掉,减少空间},}));});return plugins;
}module.exports = {entry: getEntry(), // 获取entry文件入口optimization: {moduleIds: 'deterministic',chunkIds: 'deterministic',splitChunks: {cacheGroups: getCssOutput(), // CSS输出配置},},output: {filename: 'static/js/[name].bundle.[fullhash].js',chunkFilename: 'static/js/[name].bundle.[chunkhash].js',path: path.resolve(__dirname, 'dist/'),publicPath: envConfig.PUBLIC_PATH,},resolve: {extensions: ['.js', '.json'],alias: {'@/store': path.join(__dirname, 'src/store'),'@/actions': path.join(__dirname, 'src/actions'),'@/reducers': path.join(__dirname, 'src/reducers'),'@/components': path.join(__dirname, 'src/components'),'@/containers': path.join(__dirname, 'src/containers'),'@/assets': path.join(__dirname, 'src/assets'),'@/utils': path.join(__dirname, 'src/utils'),'@/socket': path.join(__dirname, 'src/socket'),'@/reactX': path.join(__dirname, 'src/reactX'),'@/pages': path.join(__dirname, 'src/pages'),'@/img': path.join(__dirname, 'src/assets/img'),'@/hooks': path.join(__dirname, 'src/hooks'),},},module: {rules: [{test: /\.jsx?$/,exclude: /node_modules/,use: {loader: 'babel-loader',},},{test: /\.(le|c)ss$/, // .less and .cssuse: [isDevelopment? 'style-loader': {loader: MiniCssExtractPlugin.loader,options: {publicPath: '../',},},{loader: 'css-loader',options: {// url: false,sourceMap: isDevelopment,},},'less-loader',],},{test: /\.(html|htm)$/i,use: 'html-withimg-loader', // 解析 html中的图片资源},{//图片小于一定大小使用base64 否则使用file-loader产生真实图片test: /\.(png|gif|jp?g|svg|webp|ico)$/,use: [{loader: 'url-loader',options: {limit: 5000, //小于限定使用base64name: 'static/images/[name].[hash:8].[ext]',publicPath: `../../`,esModule: false,},},],},{test: /\.(eot|woff|woff2|ttf|OTF|otf)(\?.*)?$/,use: [{loader: 'file-loader',options: {name: 'static/fonts/[name].[hash:8].[ext]',publicPath: `../../`,esModule: false,},},],},{test: /\.(ogg|mp3|mp4|wav|mpe?g)$/,use: [{loader: 'file-loader',options: {publicPath: `../../`,name: 'static/medias/[name].[hash:8].[ext]',esModule: false,},},],},{test: /\.jsx?$/,include: [path.resolve(__dirname, 'src/pages/allCase/index.js')],enforce: 'post',use: {loader: WebpackObfuscator.loader,options: { rotateStringArray: true },},},],},plugins: [...[new webpack.DefinePlugin({envConfig: JSON.stringify(envConfig),}),new webpack.HotModuleReplacementPlugin(),new CleanWebpackPlugin({cleanOnceBeforeBuildPatterns: !isDevelopment? ['**/*', '!global*', '!client/js/global*', '!client/js/global/**']: [],}), // 清理非global目录文件],...getHtmlPlugin(),],stats: { warnings: false, children: false },
};
新建webpack.base.conf.js文件,部分代码仅供参考
"use strict";
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {// 入口起点entry: {app: "./src/index.js",},// 输出output: {path: path.resolve(__dirname, "../dist"),filename: "[name].js",},// 解析resolve: {extensions: [".ts", ".tsx", ".js", ".json"],alias: {"@components": path.join(__dirname, "../src/components"),"@utils": path.join(__dirname, "../src/utils"),"@pages": path.join(__dirname, "../src/pages"),},},// loadermodule: {rules: [{test: /\.js|jsx$/,exclude: /(node_modules|bower_components)/, // 屏蔽不需要处理的文件(文件夹)(可选)loader: "babel-loader",},{//支持less// npm install style-loader css-loader less-loader less --save-devtest: /\.(le|c)ss$/, // .less and .cssuse: ["style-loader", "css-loader", "less-loader"], // 创建的css文件存在html的头部},],},// 插件plugins: [new HtmlWebpackPlugin({filename: "index.html",template: "src/index.html",inject: "body",hash: false,minify: {collapseWhitespace: true, //把生成文件的内容的没用空格去掉,减少空间},}),],
};
新建webpack.development.js文件,部分代码仅供参考
"use strict";
const { merge } = require("webpack-merge");
const baseWebpackConfig = require("./webpack.base.conf");
const path = require("path");
const webpack = require("webpack");module.exports = merge(baseWebpackConfig, {// 模式mode: "development",// 调试工具devtool: "inline-source-map",// 开发服务器devServer: {static: path.resolve(__dirname, "static"),historyApiFallback: true, // 在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.htmlcompress: true, // 启用gzip压缩hot: true, // 模块热更新,取决于HotModuleReplacementPluginhost: "127.0.0.1", // 设置默认监听域名,如果省略,默认为“localhost”port: 8888, // 设置默认监听端口,如果省略,默认为“8080”},optimization: {nodeEnv: "development",},
});
新建webpack.prod.conf.js文件
"use strict";
const { merge } = require("webpack-merge");
const baseWebpackConfig = require("./webpack.base.conf");const path = require("path");
const webpack = require("webpack");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");module.exports = merge(baseWebpackConfig, {// 模式mode: "production",// 调试工具devtool: "source-map",// 输出output: {path: path.resolve(__dirname, "../dist"),filename: "js/[name].[chunkhash].js",},// 插件plugins: [new CleanWebpackPlugin()],// 代码分离相关optimization: {nodeEnv: "production",runtimeChunk: {name: "manifest",},splitChunks: {minSize: 30000,minChunks: 1,maxAsyncRequests: 5,maxInitialRequests: 3,name: false,cacheGroups: {vendor: {test: /[\\/]node_modules[\\/]/,name: "vendor",chunks: "initial",},},},},
});
新建.babelrc文件
{"presets": ["latest", "react", "stage-2"],"plugins": []
}
修改package.json中的script代码
"scripts": {"dev": "webpack-dev-server --hot --config config/webpack.dev.conf.js","start": "npm run dev","build": "webpack --progress --colors --config config/webpack.prod.conf.js"},
此时,package.json中部分代码如下
{"name": "webpack-react-demo","version": "1.0.0","description": "","main": "index.js","scripts": {"dev": "webpack-dev-server --hot --config config/webpack.dev.conf.js","start": "npm run dev","build": "webpack --progress --config config/webpack.prod.conf.js"},"license": "ISC","devDependencies": {"babel-core": "^6.26.3","babel-loader": "^7.1.5","babel-plugin-import": "^1.13.5","babel-preset-latest": "^6.24.1","babel-preset-react": "^6.24.1","babel-preset-stage-0": "^6.24.1","clean-webpack-plugin": "^4.0.0","css-loader": "^6.7.1","file-loader": "^6.2.0","html-webpack-plugin": "^5.5.0","less-loader": "^11.0.0","node-less": "^1.0.0","style-loader": "^3.3.1","url-loader": "^4.1.1","webpack": "^5.74.0","webpack-cli": "^4.10.0","webpack-dev-server": "^4.10.1","webpack-merge": "^5.8.0"},"dependencies": {"less": "^4.1.3","react": "^18.2.0","react-dom": "^18.2.0","react-router-dom": "^5.1.2"}
}
在项目中添加代码规范检测
yarn add babel-eslint --save-dev
yarn add @umijs/fabric -D //@umijs/fabric一个包含 prettier,eslint,stylelint 的配置文件合集。
yarn add prettier --save-dev //默认@umijs/fabric已经给我们安装了需要的依赖,但是默认是没有pretter。结合项目中安装eslint-plugin-react-hooks并在.eslintrc.js中配置rules:{"react-hooks/rules-of-hooks":'error',"react-hooks/exhaustive-deps":'warn',}
可以一键生成hooks依赖
新增如下文件(用于规范项目组代码)
.eslintrc.js文件
module.exports = {env: {browser: true,es2021: true,},extends: [require.resolve("@umijs/fabric/dist/eslint")],parserOptions: {ecmaFeatures: {jsx: true,},ecmaVersion: 12,sourceType: "module",},parser: "babel-eslint",globals: {gtag: true,$: true,_g_deflang: true,require: true,envConfig: true,process: true,React: true,ysf: true,initNECaptcha: true,initNECaptchaWithFallback: true,},// plugins: ["react"],rules: {//"react/jsx-uses-react": 2,"no-nested-ternary": 0, // 允许嵌套三元表达式"no-script-url": 0, // 允许javascript:;"prefer-destructuring": 0, // 关闭强制使用解构"no-plusplus": 0, // 允许使用++和--的操作"array-callback-return": 0, // 允许数组map不返回值"consistent-return": 0,"no-param-reassign": 0, // 允许修改函数形参"no-unused-expressions": 0,"no-restricted-syntax": 0,"react/prop-types": 0,"no-prototype-builtins": 0,"react/no-deprecated": 0, // 关闭react弃用检测"react/no-string-refs": 0,"no-useless-escape": 0,"react-hooks/rules-of-hooks":'error',"react-hooks/exhaustive-deps":'warn',},
};
.eslintignore文件
/lambda/
/scripts/*
.history
serviceWorker.ts
/config/*
/public/*
*.js
.prettierrc.js文件
module.exports = {singleQuote: true,jsxSingleQuote: true,semi: true,
};
.prettierignore文件
**/*.svg
package.json
.umi
.umi-production
/dist
.dockerignore
.DS_Store
.eslintignore
*.png
*.toml
docker
.editorconfig
Dockerfile*
.gitignore
.prettierignore
LICENSE
.eslintcache
*.lock
yarn-error.log
.history
.stylelintrc.js文件
const fabric = require('@umijs/fabric');
module.exports = {...fabric.stylelint,
};
替换package.json中命令
"scripts": {"lint": "umi g tmp && npm run lint:js && npm run lint:style && npm run lint:prettier","lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ","lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src && npm run lint:style","lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src","lint:prettier": "prettier --check \"src/**/*\" --end-of-line auto","lint:style": "stylelint --fix \"src/**/*.less\" --syntax less","prettier": "prettier -c --write \"src/**/*\"","precommit": "lint-staged","precommit:fix": "npm run lint:fix && npm run prettier && npm run lint:prettier && npm run lint:style","dev": "webpack-dev-server --hot --config config/webpack.dev.conf.js","start": "npm run dev","build": "webpack --progress --config config/webpack.prod.conf.js"},
安装cross-env(运行跨平台设置和使用环境变量的脚本)
1、安装:npm install --save-dev cross-env
2、修改启动命令(原命令前加上 cross-env APP_ENV=development 环境变量):"start:dev": "cross-env APP_ENV=development webpack serve --config webpack.development.js","testing": "cross-env APP_ENV=testing webpack --config webpack.testing.js","build": "cross-env APP_ENV=production webpack --config webpack.production.js","preBuild": "cross-env APP_ENV=preProduction webpack --config webpack.production.js",
3、读取环境变量:process.env.APP_ENV
添加提交前检测
#使用husky lint-staged在commit的时候校检你提交的代码是否符合规范
yarn add husky lint-staged -D
package.json新增如下代码
"lint-staged": {"**/*.less": "stylelint--syntaxless","**/*.{js,jsx,ts,tsx}": "npmrunlint-staged:js","**/*.{js,jsx,tsx,ts,less,md,json}": ["prettier--write"]},"husky": {"hooks": {"pre-commit": "npmrunlint-staged"}}
package.json中全部代码如下
{"name": "reactt-home","version": "1.0.0","description": "reactt-home","main": "index.js","scripts": {"lint": "eslint --ext .js --ext .jsx src","start": "cross-env APP_ENV=development webpack serve --config webpack.development.js","testing": "cross-env APP_ENV=testing webpack --config webpack.testing.js","build": "cross-env APP_ENV=production webpack --config webpack.production.js","preBuild": "cross-env APP_ENV=preProduction webpack --config webpack.production.js","lint-staged": "lint-staged","lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ","lint:fix": "eslint --fix --quiet --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src && npm run lint:style","lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src","lint:prettier": "prettier --check \"**/*\" --end-of-line auto","lint:style": "stylelint --fix \"src/**/*.less\" --syntax less","prettier": "prettier -c --write \"**/*\""},"author": "shenzhihao","license": "ISC","devDependencies": {"@babel/core": "^7.7.4","@babel/plugin-proposal-class-properties": "^7.7.4","@babel/plugin-transform-object-assign": "^7.8.3","@babel/plugin-transform-runtime": "^7.7.4","@babel/polyfill": "^7.7.0","@babel/preset-env": "^7.7.4","@babel/preset-react": "^7.7.4","@babel/runtime": "^7.7.4","@pmmmwh/react-refresh-webpack-plugin": "^0.5.7","babel-eslint": "^10.1.0","babel-loader": "^8.0.6","babel-plugin-import": "^1.13.0","clean-webpack-plugin": "^3.0.0","compression-webpack-plugin": "^6.0.5","copy-webpack-plugin": "^11.0.0","cross-env": "^7.0.3","css-loader": "^3.2.1","css-minimizer-webpack-plugin": "^4.0.0","css-vars-ponyfill": "^2.4.7","eslint": "^7.25.0","eslint-formatter-pretty": "^4.0.0","eslint-plugin-import": "^2.22.1","eslint-plugin-jsx-a11y": "^6.4.1","eslint-plugin-prettier": "^3.4.0","eslint-plugin-react": "^7.23.2","eslint-plugin-react-hooks": "^4.2.0","file-loader": "^5.0.2","files-finder": "0.0.5","html-webpack-plugin": "^5.5.0","html-withimg-loader": "^0.1.16","image-webpack-loader": "^6.0.0","javascript-obfuscator": "^4.0.0","less": "^3.10.3","less-loader": "^7.0.1","lint-staged": "^11.0.0","mini-css-extract-plugin": "^2.6.1","pre-commit": "^1.2.2","prettier": "^2.2.1","react": "^18.3.1","react-dom": "^18.3.1","react-redux": "^7.1.3","react-refresh": "^0.14.0","react-router-dom": "^5.1.2","react-router-redux": "^4.0.8","redux": "^4.0.4","redux-actions": "^2.6.5","redux-logger": "^3.0.6","redux-thunk": "^2.3.0","style-loader": "^1.0.1","stylelint": "^13.13.1","stylelint-config-css-modules": "^2.2.0","stylelint-config-prettier": "^8.0.2","stylelint-config-rational-order": "^0.1.2","stylelint-config-standard": "^22.0.0","stylelint-declaration-block-no-ignored-properties": "^2.3.0","stylelint-no-unsupported-browser-features": "^4.1.4","stylelint-order": "^4.1.0","terser-webpack-plugin": "^5.3.3","url-loader": "^3.0.0","webpack": "^5.73.0","webpack-cli": "^4.2.0","webpack-dev-server": "^3.11.0","webpack-merge": "^4.2.2","webpack-obfuscator": "^3.5.1"},"dependencies": {"axios": "^0.19.0","classnames": "^2.2.6","cross-env": "^7.0.3","history": "^4.10.1","paho-mqtt": "^1.1.0"},"pre-commit": "lint-staged","lint-staged": {"**/*.less": "stylelint --syntax less","**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js","**/*.{js,jsx,tsx,ts,less,md,json}": ["prettier --write"]}
}
三、在JS项目中添加TS
tsconfig.json配置文件
{"compilerOptions": {"incremental": true ,//增量编译"tsBuildInfoFile": ".tsbuildinfo", //增量编译文件的存储位置"diagnostics": true, //打印诊断信息"target": "ES5", //目标语言版本"module": "commonjs",//生成代码的模块标准"outFile": "./app.js", //将多个相互依赖的文件生成一个文件,可以用在AMD模块中"lib": [], //TS需要引用的库,即声明文件"allowJs": true, //允许编辑JS文件(js,jsx)"outDir": "./out", //指定输出的目录"rootDir": "./" ,//指定输入文件目录 (用于输出)"declaration": false, //生成声明文件"declarationDir": "./d", //声明文件的路径"emitDeclarationOnly": false ,//只生成声明文件"sourceMap": false, //生成目标文件的sourecMap"inlineSourceMap": false,//声明目标文件的inline sourceMap"declarationMap": false,//生成声明文件的sourceMap"typeRoots": [], //声明文件目录 默认node_modules/@types"types": [], //声明文件包"removeComments": false, //删除注释"noEmit": false ,//不输出文件"noEmitOnError": false,//发生错误时不输出文件"noEmitHelpers": false, //不生成helper函数,需要额外安装 ts-helpers"importHelpers": false,//通过tslib引入helper函数,文件必须是模块"downlevelIteration": false,//降级遍历器的实习(es3/es5)"strict": false, //严格的类型检查"alwaysStrict": false,//在代码中注入use strict"strictNullChecks": false, //不允许把null,undefined赋值给其他类型变量"strictFunctionTypes": false, //不允许函数参数双向协变"strictPropertyInitialization": false,//类的实例属性必须初始化"strictBindCallApply": false,//严格的bind/call/apply检查"noImplicitThis": false,//不允许this有隐式的any类型"noUnusedLocals": false,//检查只声明,未使用的局部变量"noUnusedParameters": false,//检查未使用的函数参数"noFallthroughCasesInSwitch": false,//防止switch语句贯穿"noImplicitReturns": false,//每个分支都要有返回值"esModuleInterop": false ,//允许export = 导出, 由import from导入"allowUmdGlobalAccess": false,//允许在模块中访问UMD全局变量"moduleResolution": "node", //模块解析策略"baseUrl": "",//解析非相对模块的基地址"paths": {} ,//路径映射,相对于baseUrl"rootDirs": [], //将多个目录放在一个虚拟目录下,用于运行时"listEmittedFiles": false, //打印输入的文件"listFiles": false,//打印编译的文件(包括引用的声明文件)}
}
package.json部分
安装 typescript和ts-loader
yarn add typescript --D
安装react类型配置
yarn add @types/node @types/react @types/react-dom @types/react-router-dom
初始化 tsconfig.json 文件
npx tsc --init
配置 tsconfig.json
{"compilerOptions": {"target": "es2016", /**指定ECMAScript目标版本**/ "module": "commonjs", /**指定生成哪个模块系统代码**/"esModuleInterop": true,"allowJs": true, /**允许编译js文件**/ "jsx": "preserve", /**支持JSX**/ "outDir": "dist", /**编译输出目录**/ "strict": true, /**启用所有严格类型检查选项**/"noImplicitAny": false, /**在表达式和声明上有隐含的any类型时报错**/ "skipLibCheck": true, /**忽略所有的声明文件的类型检查**/ "forceConsistentCasingInFileNames": true /**禁止对同一个文件的不一致的引用**/ },"include": ["src"],"exclude": ["node_modules"]
}
package.json中scripts新增tsc命令用于检测typescript类型
"tsc": "tsc --noEmit"
Webpack部分
安装ts-loader
yarn add ts-loader eslint-import-resolver-typescript --D
reslove:extensions新增.ts和.tsx
resolve: {extensions: ['.js', '.json', '.ts', '.tsx'],
}
配置webpack,新增ts-loader
{test: /\.tsx?$/, // .ts或者tsx后缀的文件,就是typescript文件use: 'babel-loader', exclude: /node-modules/, // 排除node-modules目录
}
安装@babel/preset-typescript
yarn add @babel/preset-typescript -D
.babelrc新增typescript配置
"presets": [..."@babel/typescript"
],
Eslint部分
安装@typescript-eslint/parser和@typescript-eslint/eslint-plugin
yarn add @typescript-eslint/parser @typescript-eslint/eslint-plugin -D
引入eslint三方配置
yarn add eslint-plugin-shopify -D
.eslintrc.js中新增overrides,检测.ts文件
overrides: [{files: ['*.ts', '*.tsx'],parser: '@typescript-eslint/parser',settings: {'import/resolver': {node: {extensions: ['.js', '.jsx', '.ts', '.tsx', '.css'],},typescript: {alwaysTryTypes: true,},},},plugins: ['@typescript-eslint'],extends: ['plugin:shopify/esnext'],parserOptions: {// project: './tsconfig.json',ecmaFeatures: {jsx: true,},ecmaVersion: 12,sourceType: 'module',},rules: {'no-console': 0, // 如果有console,阻止抛出错误'no-use-before-define': 'off',},},],
.eslintignore新增忽略文件tsconfig.json
.prettier新增
// jsxSingleQuote: true,
extends: ['plugin:shopify/typescript','plugin:shopify/react','plugin:shopify/prettier',],
Tips:
eslint不会报告typescript类型错误,ts如需要检测类型需要使用tsc --noEmit命令
四、本地修改依赖包并应用
本地依赖包版本控制
版本号通常由三部分组成:主版本号、次版本号、补丁版本号,格式为 major.minor.patch。常见的符号有:^:更新时允许自动更新次版本号和补丁版本号,但不会更新主版本号(即不允许跨越大版本升级)。
~:更新时只允许更新补丁版本号,不更新次版本号。
> 或<:指定大于或小于某个版本。
=:指定精确的版本号。
使用 patch-package 工具
1. 安装 patch-package
:
2. npm install --save-dev patch-package 或 yarn add patch-package -D
3. 修改依赖包源码:
4. 找到需要修改的依赖包文件路径,例如 node_modules/<dependency-name>/<file-to-patch>
。
5. 对文件进行所需的修改。
6. 创建补丁文件:
7. npx patch-package
8. 这将创建一个 .patch
文件在项目的根目录下。
9. 提交补丁文件到版本控制系统: 将生成的 .patch
文件提交到你的版本控制系统中。
10. 自动应用补丁
11. 为了确保每次 npm install
都能自动应用这些补丁,你需要在 package.json
的 scripts
字段中添加一条命令:
12. { "scripts": { "postinstall": "patch-package" } }
13. 这样,在每次执行 npm install
后,patch-package
将会自动查找 .patch
文件并应用它们到相应的 node_modules
中。
相关文章:
现代前端工程化实践:高效构建的秘密
一、前端工程化错误监控 这种监控可以帮助开发人员及时发现和解决问题,提高应用程序的稳定性和可靠性。 1. Sentry:Sentry是一款开源的错误监控平台,可以监控前端、后端以及移动端应用程序中的错误和异常。Sentry提供了实时错误报告、错误分…...

ARM Linux Qt使用JSON-RPC实现前后台分离
文章目录 1、前言2、解决方案2.1、JSON-RPC2.2、Qt中应用JSON-RPC的框架图2.3、优点2.4、JSON-RPC 1.0 协议规范 3、程序示例3.1、Linux C(只例举RPC Server相关程序)3.2、Qt程序(只例举RPC Client相关程序) 4、编译程序4.1、交叉…...

【C++篇】C++11新特性总结1
目录 1,C11的发展历史 2,列表初始化 2.1C98传统的{} 2.2,C11中的{} 2.3,C11中的std::initializer_list 3,右值引用和移动语义 3.1,左值和右值 3.2,左值引用和右值引用 3.3,…...
【Nginx + Keepalived 实现高可用的负载均衡架构】
使用 Nginx Keepalived 可以实现高可用的负载均衡架构,确保在某个 Nginx 节点故障时,自动将流量转移到备用节点。以下是详细的实现步骤: 1. 架构概述 Nginx:作为负载均衡器,将流量分发到后端服务器。Keepalived&…...

使用外骨骼灵活远程控制协作机器人案例
外骨骼控制器采用可调节结构,简化了机器人编程,使协作机器人 FR3 的远程控制变得容易。 一、引言 在开发机器人手臂或双臂系统的应用程序时,经常会遇到以下挑战: 1. 使用拖动和示教进行定位的困难:拖动和示教功能通常…...
Centos Stream 10 根目录下的文件夹结构
/ ├── bin -> usr/bin ├── boot ├── dev ├── etc ├── home ├── lib -> usr/lib ├── lib64 -> usr/lib64 ├── lostfound ├── media ├── mnt ├── opt ├── proc ├── root ├── run ├── sbin -> usr/sbin ├── srv ├─…...
python连点器
要实现一个用于抖音点赞的鼠标连点工具,可以通过编程或现有软件实现。以下是两种常见方法(但请注意:频繁自动化操作可能违反平台规则,需谨慎使用): 方法 1:使用现成工具(如 AutoClic…...

STM32G474--Whetstone程序移植(单精度)笔记
1 准备基本工程代码 参考这篇笔记从我的仓库中选择合适的基本工程,进行程序移植。这里我用的是stm32g474的基本工程。 使用git clone一个指定文件或者目录 2 移植程序 2.1 修改Whetstone.c 主要修改原本变量定义的类型,以及函数接口全部更换为单精度…...

Spring Boot 3.4 中 MockMvcTester 的新特性解析
引言 在 Spring Boot 3.4 版本中,引入了一个全新的 MockMvcTester 类,使 MockMvc 测试可以直接支持 AssertJ 断言。本文将深入探讨这一新特性,分析它如何优化 MockMvc 测试并提升测试的可读性。 Spring MVC 示例 为了演示 MockMvcTester 的…...

java 读取sq3所有表数据到objectNode
1.实现效果:将sq3中所有表的所有字段读到objectNode 对象中,兼容后期表字段增删情况,数据组织形式如下图所示: 代码截图: 代码如下: package com.xxx.check.util;import java.sql.*; import java.util.Arr…...

网络计算机的五个组成部分
单个计算机是无法进行通信的。所以需要借助网络。 下面介绍一些在网络里常见的设备。 一、服务器 服务器是在网络环境中提供计算能力并运行软件应用程序的特定IT设备 它在网络中为其他客户机(如个人计算机、智能手机、ATM机等终端设备)提供计算或者应用…...
jakarta EE学习笔记-个人笔记
WebServlet注解:声明一个类为Servlet Target({ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Documented public interface WebServlet {// 指定Servlet的影子String name() default ""; // 匹配地址映射(URL)String[] value() default {};// …...
vue3-响应式 toRefs
在Vue 3中,toRefs是一个非常有用的组合式API(Composition API)函数,它主要用于将响应式对象(通常是由reactive创建的对象)转换为单独的响应式引用对象。这样做的好处是可以将这些响应式引用解构出来&#x…...

学习threejs,使用Lensflare模拟镜头眩光
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.Lensflare 二、&…...

redis高级数据结构布隆过滤器
文章目录 背景什么是布隆过滤器Redis 中的布隆过滤器布隆过滤器使用注意事项实现原理空间占用估计 背景 我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经看过的内容。问题来了,新闻…...
mysql 5.7安装
基础环境:centos7.9 创建日志存放目录 mkdir -p /opt/supervisor/log安装相关工具 yum install -y perl net-tools numactl gcc python-devel配置yum源 sudo vim /etc/yum.repos.d/mysql-community.repo [mysql-connectors-community] nameMySQL Connectors Com…...

Golang:精通sync/atomic 包的Atomic 操作
在本指南中,我们将探索sync/atomic包的细节,展示如何编写更安全、更高效的并发代码。无论你是经验丰富的Gopher还是刚刚起步,你都会发现有价值的见解来提升Go编程技能。让我们一起开启原子运算的力量吧! 理解Go中的原子操作 在快…...

微信小程序如何使用decimal计算金额
第三方库地址:GitHub - MikeMcl/decimal.js: An arbitrary-precision Decimal type for JavaScript 之前都是api接口走后端计算,偶尔发现这个库也不错,计算简单,目前发现比较准确 上代码 导入js import Decimal from ../../uti…...
最新Modular公司之MAX和Mojo作者 克里斯·拉特纳简介
Chris Lattner(克里斯拉特纳) 是一位著名的计算机科学家和软件工程师,以其在编程语言、编译器技术和软件开发工具领域的贡献而闻名。以下是关于他的详细介绍: 1. 主要成就 (1)LLVM 项目的创始人 Chris La…...

Redis数据库篇 -- Pipeline
一. 什么是Pipeline 在传统的请求-响应模式中,客户端与服务器之间的通信流程如下: 客户端发送一个命令到服务器。服务器接收命令并执行。服务器将执行结果返回给客户端。客户端接收结果后,发送下一个命令 在这种传统的模式下,…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...