现代前端工程化实践:高效构建的秘密
一、前端工程化错误监控
这种监控可以帮助开发人员及时发现和解决问题,提高应用程序的稳定性和可靠性。
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 在传统的请求-响应模式中,客户端与服务器之间的通信流程如下: 客户端发送一个命令到服务器。服务器接收命令并执行。服务器将执行结果返回给客户端。客户端接收结果后,发送下一个命令 在这种传统的模式下,…...

爬虫自动化(DrissionPage)
目录 ?一.介绍: 下载DrissionPage,还是我们熟悉的pip: 环境准备: ?二.基本代码: 它对于的导包和类使用: 窗口的设置: 和获取的页面的滑动: 3.进一步认识DrissionPage: 浏览器可以多开…...

常见string库中的函数(C语言超详细)
文章目录 strcspnstrcpystrncpystrcatstrncatstrcmpstrncmpstrchrstrrchrstrstrstrtokstrlenstrnlen strcspn 原型: size_t strcspn(const char *str1, const char *str2);功能: strcspn 会扫描 str1,并返回一个整数,表示 str1 中第一个匹配…...

单例模式几种实现
静态内部类holder实现(推荐) public class UniqueIdGenerator {public static final UniqueIdGenerator INSTANCE Holder.INSTANCE;// Private holder class for lazy initializationprivate static class Holder {static final UniqueIdGenerator INS…...

android中关于CheckBox自定义选中图片选中无效问题
在android xml 布局中,使用CheckBox控件设置选中背景图代码如下 <CheckBoxandroid:layout_width"wrap_content"android:layout_height"wrap_content"android:button"drawable/dfrd_common_selecotr_check"android:paddingStart&q…...

虚拟局域网之详解(Detailed Explanation of Virtual Local Area Network)
虚拟局域网之详解 VLAN (virtual localArea network)是一种虚拟局域网技术,它可以将一个物理局域网划分为多个逻辑上的虚拟局域网。 基于交换式以太网的虚拟局域网在交换式以太网中,利用VLAN技术,可以将由交换机连接成的物理网络划分成多个…...

双亲委派(JVM)
1.双亲委派 在 Java 中,双薪委派通常是指双亲委派模型,它是 Java 类加载器的一种工作模式,用于确保类加载的安全性和一致性。以下是其相关介绍: 定义与作用 定义:双亲委派模型要求除了顶层的启动类加载器外…...

第二十一章:考研的艰难抉择与放弃入学的转折
深秋时节,校园宛如被大自然精心雕琢的艺术殿堂。金黄的银杏叶在阳光的轻抚下,闪烁着细碎的光芒,微风拂过,叶片相互摩挲,发出沙沙的轻响,仿佛在低声诉说着岁月的故事。一片片银杏叶悠悠然飘落,宛…...

webpack配置之---output.chunkLoading
output.chunkLoading webpack.output.chunkLoading 配置项用于指定 Webpack 如何加载异步 chunk(即按需加载的代码块)。在现代 Webpack 版本中,异步代码分割成为了非常常见的功能,chunkLoading 配置项就用于控制 Webpack 加载这些…...

升级RAG应用程序与Redis向量库
Redis Vector Library (RedisVL) 简化AI应用开发 几个月前,Redis推出了Redis向量库(RedisVL),以简化人工智能(AI)应用的开发。自那时起,我们引入了强大的新功能,支持大规模的语言模…...

【starrocks学习】之将starrocks表同步到hive
目录 方法 1:通过HDFS导出数据 1. 将StarRocks表数据导出到HDFS 2. 在Hive中创建外部表 3. 验证数据 方法 2:使用Apache Spark同步 1. 添加StarRocks和Hive的依赖 2. 使用Spark读取StarRocks数据并写入Hive 3. 验证数据 方法 3:通过…...