diff --git a/.eslintrc.js b/.eslintrc.js index 7f32bb5..88ec192 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -37,7 +37,8 @@ module.exports = { settings: { 'import/resolver': { node: { - extensions: ['.ts', '.tsx', '.js', '.json'], + // import 模块时,不写后缀将尝试导入的后缀,出现频率高的文件类型放前面 + extensions: ['.tsx', '.ts', '.js', '.json'], }, typescript: { directory: [resolve('./src/tsconfig.json'), resolve('./scripts/tsconfig.json')], @@ -61,7 +62,7 @@ module.exports = { 'unicorn/prevent-abbreviations': OFF, 'unicorn/filename-case': [ - 'error', + ERROR, { cases: { // 中划线 diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..2e7fd7a --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,13 @@ +// https://gist.github.com/tjx666/daa6317cf80ab5f467c50b2693527875 +{ + "recommendations": [ + "editorconfig.editorconfig", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "stylelint.vscode-stylelint", + "dsznajder.es7-react-js-snippets", + "mrmlnc.vscode-scss", + "yutengjing.view-github-repository", + "yutengjing.open-in-external-app" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index c407e6a..4e1bb15 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,8 @@ { + // stylelint 扩展自身的校验就够了 + "css.validate": false, + "less.validate": false, + "scss.validate": false, // 使用本地安装的 TypeScript 替代 VSCode 内置的来提供智能提示 "typescript.tsdk": "./node_modules/typescript/lib", // 指定哪些文件不参与搜索 @@ -12,8 +16,7 @@ "**/.git/objects/**": true, "**/.git/subtree-cache/**": true, "**/node_modules/*/**": true, - "dist": true, - "yarn.lock": true + "**/dist/**": true }, // 配置 VScode 使用 prettier 的 formatter "[javascript]": { diff --git a/babel.config.js b/babel.config.js index ef139d7..32b3192 100644 --- a/babel.config.js +++ b/babel.config.js @@ -10,11 +10,17 @@ const envPreset = [ }, ]; -module.exports = function(api) { +module.exports = function (api) { api.cache(true); return { presets: ['@babel/preset-typescript', envPreset], - plugins: ['@babel/plugin-transform-runtime'], + plugins: [ + '@babel/plugin-transform-runtime', + '@babel/plugin-syntax-dynamic-import', + '@babel/plugin-proposal-optional-chaining', + ['@babel/plugin-proposal-class-properties', { loose: true }], + ['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }], + ], env: { development: { presets: [['@babel/preset-react', { development: true }]], diff --git a/postcss.config.js b/postcss.config.js index 57c9c63..1ac57dc 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,4 +1,4 @@ -/* eslint-disable global-require, @typescript-eslint/no-var-requires */ +/* eslint-disable global-require, import/no-extraneous-dependencies, @typescript-eslint/no-var-requires */ module.exports = { plugins: [ diff --git a/scripts/configs/proxy.ts b/scripts/configs/proxy.ts index d7f03b4..1b0354a 100644 --- a/scripts/configs/proxy.ts +++ b/scripts/configs/proxy.ts @@ -1,7 +1,7 @@ -import { ProxyTable } from '../typings/devServer'; +import { ProxyTable } from '../typings/server'; const proxyTable: ProxyTable = { - '/path_to_be_proxy': { target: 'http://target.domain.com', changeOrigin: true }, + // '/path_to_be_proxy': { target: 'http://target.domain.com', changeOrigin: true }, }; export default proxyTable; diff --git a/scripts/configs/webpack.common.ts b/scripts/configs/webpack.common.ts index b801441..9d7d110 100644 --- a/scripts/configs/webpack.common.ts +++ b/scripts/configs/webpack.common.ts @@ -1,18 +1,16 @@ import { resolve } from 'path'; -import { BannerPlugin, Configuration } from 'webpack'; +import { Configuration } from 'webpack'; import WebpackBar from 'webpackbar'; import FriendlyErrorsPlugin from 'friendly-errors-webpack-plugin'; // import WebpackBuildNotifierPlugin from 'webpack-build-notifier'; -import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin'; -import CircularDependencyPlugin from 'circular-dependency-plugin'; import { CleanWebpackPlugin } from 'clean-webpack-plugin'; import HtmlWebpackPlugin from 'html-webpack-plugin'; +// eslint-disable-next-line import/no-unresolved import { Options as HtmlMinifierOptions } from 'html-minifier'; import CopyPlugin from 'copy-webpack-plugin'; -import HardSourceWebpackPlugin from 'hard-source-webpack-plugin'; import { loader as MiniCssExtractLoader } from 'mini-css-extract-plugin'; -import { __DEV__, COPYRIGHT, PROJECT_NAME, PROJECT_ROOT, HMR_PATH } from '../utils/constants'; +import { __DEV__, PROJECT_NAME, PROJECT_ROOT, HMR_PATH } from '../utils/constants'; function getCssLoaders(importLoaders: number) { return [ @@ -50,6 +48,7 @@ const htmlMinifyOptions: HtmlMinifierOptions = { }; const commonConfig: Configuration = { + cache: true, context: PROJECT_ROOT, entry: ['react-hot-loader/patch', resolve(PROJECT_ROOT, './src/index.tsx')], output: { @@ -59,8 +58,8 @@ const commonConfig: Configuration = { hashSalt: PROJECT_NAME, }, resolve: { - // 指定 webpack 在 require 模块时,尝试使用的后缀名 - extensions: ['.ts', '.tsx', '.js', '.json'], + // 我们导入ts 等模块一般不写后缀名,webpack 会尝试使用这个数组提供的后缀名去导入 + extensions: ['.js', '.tsx', '.ts', '.json'], alias: { // 替换 react-dom 成 @hot-loader/react-dom 以支持 react hooks 的 hot reload 'react-dom': '@hot-loader/react-dom', @@ -73,19 +72,8 @@ const commonConfig: Configuration = { // react 蓝 color: '#61dafb', }), - new BannerPlugin({ - raw: true, - banner: COPYRIGHT, - }), new FriendlyErrorsPlugin(), // new WebpackBuildNotifierPlugin({ suppressSuccess: true }), - new CaseSensitivePathsPlugin(), - new CircularDependencyPlugin({ - exclude: /node_modules/, - failOnError: true, - allowAsyncCycles: false, - cwd: PROJECT_ROOT, - }), new CleanWebpackPlugin(), new HtmlWebpackPlugin({ // HtmlWebpackPlugin 会调用 HtmlMinifier 对 HTMl 文件进行压缩 @@ -122,7 +110,6 @@ const commonConfig: Configuration = { ], { context: resolve(PROJECT_ROOT, './public') }, ), - new HardSourceWebpackPlugin({ info: { mode: 'none', level: 'warn' } }), ], module: { rules: [ diff --git a/scripts/configs/webpack.dev.ts b/scripts/configs/webpack.dev.ts index 74555e4..866ad9e 100644 --- a/scripts/configs/webpack.dev.ts +++ b/scripts/configs/webpack.dev.ts @@ -1,6 +1,6 @@ import { resolve } from 'path'; import merge from 'webpack-merge'; -import { HotModuleReplacementPlugin, NamedModulesPlugin } from 'webpack'; +import { HotModuleReplacementPlugin } from 'webpack'; import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; import commonConfig from './webpack.common'; @@ -8,17 +8,15 @@ import { PROJECT_ROOT } from '../utils/constants'; const devConfig = merge(commonConfig, { mode: 'development', - // 觉得打包速度慢可以考虑改成 cheap-eval-source-map,但是这种 sourceMap 不会显示列号 // 如果觉得还可以容忍更慢的非 eval 类型的 sourceMap,可以搭配 error-overlay-webpack-plugin 使用 - devtool: 'eval-source-map', + // 需要显示列号可以切换成 eval-source-map + devtool: 'cheap-module-eval-source-map', plugins: [ new ForkTsCheckerWebpackPlugin({ memoryLimit: 1024, tsconfig: resolve(PROJECT_ROOT, './src/tsconfig.json'), }), new HotModuleReplacementPlugin(), - // 会在浏览器控制台显示每次修改的模块 - new NamedModulesPlugin(), ], }); diff --git a/scripts/configs/webpack.prod.ts b/scripts/configs/webpack.prod.ts index 06b47fc..fa8a3b5 100644 --- a/scripts/configs/webpack.prod.ts +++ b/scripts/configs/webpack.prod.ts @@ -1,4 +1,5 @@ import { resolve } from 'path'; +import { BannerPlugin } from 'webpack'; import merge from 'webpack-merge'; import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; import MiniCssExtractPlugin from 'mini-css-extract-plugin'; @@ -10,11 +11,15 @@ import CompressionPlugin from 'compression-webpack-plugin'; import SizePlugin from 'size-plugin'; import commonConfig from './webpack.common'; -import { ENABLE_ANALYZE, PROJECT_ROOT } from '../utils/constants'; +import { COPYRIGHT, ENABLE_ANALYZE, PROJECT_ROOT } from '../utils/constants'; const mergedConfig = merge(commonConfig, { mode: 'production', plugins: [ + new BannerPlugin({ + raw: true, + banner: COPYRIGHT, + }), new ForkTsCheckerWebpackPlugin({ // 生产环境打包并不频繁,可以适当调高允许使用的内存,加快类型检查速度 memoryLimit: 1024 * 2, diff --git a/scripts/typings/devServer.d.ts b/scripts/typings/server.d.ts similarity index 100% rename from scripts/typings/devServer.d.ts rename to scripts/typings/server.d.ts diff --git a/src/tsconfig.json b/src/tsconfig.json index afb2d4c..93264a3 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -17,6 +17,11 @@ "moduleResolution": "node", "esModuleInterop": true, "resolveJsonModule": true, + "baseUrl": "./", + "paths": { + // 配置模块路径映射 + "@/*": ["./*"] + }, /* Experimental Options */ "experimentalDecorators": true, @@ -24,6 +29,10 @@ /* Advanced Options */ "forceConsistentCasingInFileNames": true, - "skipLibCheck": true + "skipLibCheck": true, + + // 下面这些选项对 babel 编译 TypeScript 没有作用但是可以让 VSCode 等编辑器正确提示错误 + "target": "ES2019", + "module": "ESNext" } }