From d49f3976ec7c5368665814fb94f24f1f6948e1a1 Mon Sep 17 00:00:00 2001 From: Ray Chen Date: Mon, 7 Feb 2022 10:59:43 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=BC=80=E5=85=B3=20erro?= =?UTF-8?q?r=20overlay=20(#161)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: add error overlay config * fix: default false * docs: update doc * fix: default enable * fix: remove space --- build-config.md | 8 ++++++++ preset-configs/config.schema.json | 4 ++++ preset-configs/default.json | 3 ++- src/utils/build-conf.ts | 2 ++ src/webpack/index.ts | 6 +++++- 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/build-config.md b/build-config.md index 86ed1db..ddeeb9a 100644 --- a/build-config.md +++ b/build-config.md @@ -312,6 +312,14 @@ const apiUrl = "http://foobar.com/api" + 'test' 这里传入 `true` 表示启用文件系统缓存,`false` 则不启用。 +- **`optimization.errorOverlay`** + + 类型:`boolean` + + 是否开启 `react-refresh-webpack-plugin` 的错误提示。 + + `true` 表示开启,`false` 表示关闭,默认开启。 + ## **`devProxy`** 类型:`object` diff --git a/preset-configs/config.schema.json b/preset-configs/config.schema.json index d2e3c70..1ed3916 100644 --- a/preset-configs/config.schema.json +++ b/preset-configs/config.schema.json @@ -162,6 +162,10 @@ "filesystemCache": { "type": "boolean", "description": "是否启用文件系统缓存,用于提升二次启动的打包速度,对于大型的前端仓库提升效果尤其明显。\n这里传入 `true` 表示启用文件系统缓存,`false` 则不启用。" + }, + "errorOverlay": { + "type": "boolean", + "description": "是否开启 `react-refresh-webpack-plugin` 的错误提示。 \n`true` 表示开启,`false` 表示关闭,默认开启。" } } }, diff --git a/preset-configs/default.json b/preset-configs/default.json index 87cea36..8295d5d 100644 --- a/preset-configs/default.json +++ b/preset-configs/default.json @@ -65,7 +65,8 @@ "compressImage": false, "transformDeps": false, "highQualitySourceMap": false, - "filesystemCache": true + "filesystemCache": true, + "errorOverlay": true }, "devProxy": {}, "deploy": { diff --git a/src/utils/build-conf.ts b/src/utils/build-conf.ts index b0ae0f8..3a1e771 100644 --- a/src/utils/build-conf.ts +++ b/src/utils/build-conf.ts @@ -55,6 +55,8 @@ export interface Optimization { highQualitySourceMap: boolean /** 是否启用文件系统缓存 */ filesystemCache: boolean + /** 是否开启 react-refresh-webpack-plugin 的错误提示 */ + errorOverlay: boolean } export interface EnvVariables { diff --git a/src/webpack/index.ts b/src/webpack/index.ts index 23a2f00..f18ea13 100644 --- a/src/webpack/index.ts +++ b/src/webpack/index.ts @@ -164,10 +164,14 @@ export async function getConfig(): Promise { /** 获取 webpack 配置(dev server 用,不含 dev server 配置) */ export async function getServeConfig() { + const buildConfig = await findBuildConfig() + const { errorOverlay } = buildConfig.optimization const config = await getConfig() return appendPlugins( config, - new ReactFastRefreshPlugin() + new ReactFastRefreshPlugin({ + overlay: errorOverlay + }) ) } From 1e91aec6996343e04498828191fdbbd799c8aa20 Mon Sep 17 00:00:00 2001 From: Hanxing Yang Date: Tue, 8 Feb 2022 11:55:32 +0800 Subject: [PATCH 2/4] add section Contributing to README (#162) --- README.md | 63 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 21b2c9f..f26fd40 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,47 @@ VSCode 中可以通过安装插件 [fec-builder-helper](https://marketplace.visu 同 `ts` 的 `transpileOnlyWhenDev` 配置 +### Contributing + +##### 1. Fork 并 clone 到本地 + +```shell +git clone --recurse-submodules +``` + +注意这里 clone 时需要指定 `--recurse-submodules`,以确保 repo 中的 `samples/` 内容可以被正确地拉取。 + +##### 2. 安装依赖 + +注意这里需要使用 npm —— builder 使用 npm shrinkwrap file 来锁定依赖,因此使用 yarn 或别的不支持 npm shrinkwrap 的包管理安装依赖可能会引入问题。 + +```shell +npm i +``` + +##### 3. 本地执行 builder + +```shell +npm run dev +``` + +通过 npm script `dev`,我们会使用当前的 builder 代码,基于 `samples/typescript-react` 项目启动开发服务器(监听 80 端口)。 + +每次修改 builder 本身的代码后,需要重新执行命令以运行最新的代码。 + +##### 4. 指定项目或命令 + +参考 npm script `dev` 的内容(`ts-node ./src/bin.ts -r ./samples/typescript-react`),我们可以通过直接执行 `ts-node` 来指定项目的目录或 builder 的命令,如 + +```shell +npx ts-node ./src/bin.ts generate -r ./samples/hello-world +``` + +相当于在 `./samples/hello-world` 目录下执行 + +```shell +fec-builder generate +``` ### CHANGELOG @@ -131,25 +172,3 @@ debug babel 配置 ##### 1.0.0 可用 - -### 常见问题 - -##### CPU 占用率异常 - -如发现 builder 的 npm 包执行出现 cpu 占用极高的情况(不编译时都 90%+),很可能是依赖 fsevents 没有正确安装,可以去 fec-builder 包的安装目录(一般是 `/usr/local/lib/node_modules/fec-builder`)下执行: - -```shell -npm i fsevents@1.0.17 -``` - -待安装成功后重新运行 fec-builder 即可 - -##### 使用 Typescript 时没有 [Tree Shaking](https://webpack.js.org/guides/tree-shaking/) 的效果 - -Tree Shaking 功能的生效需要由 Webpack 来处理 ES6 的 module 格式,所以在 Webpack 之前(loader 中)对 ES6 module 进行转换(如转换为 CommonJS 格式)的话,会导致构建没有 Tree Shaking 的效果。如果你在使用 Typescript,很可能是配置 Typescript 输出了 CommonJS 的结果。 - -修正做法:配置项目根目录下的 `tsconfig.json`,配置其中 `compilerOptions` 中的 `module` 值为 `ES6` 即可;或者不对 `compilerOptions.module` 进行配置,直接配置 `compilerOptions.target` 为 `ES6` 或更高(`ES2016`, `ES2017` 或 `ESNext`)亦可。 - -##### Error: EACCES, mkdir '/usr/local/lib/node_modules/fec-builder/node_modules/node-sass' - -参考 https://github.com/sass/node-sass/issues/1098 From 20019a12563a7145e52de376e1ff38f407ca1f6f Mon Sep 17 00:00:00 2001 From: Hanxing Yang Date: Thu, 17 Feb 2022 11:49:28 +0800 Subject: [PATCH 3/4] Optimize behavior for rare use cases (`serve -e prod` & `generate -e dev`) (#163) * Optimize generate result when env: dev * support `serve -e production` * debug dev --- src/serve.ts | 4 +-- src/utils/webpack.ts | 2 +- src/webpack/index.ts | 77 ++++++++++++++++++++++++++------------------ 3 files changed, 48 insertions(+), 35 deletions(-) diff --git a/src/serve.ts b/src/serve.ts index 7b1cb26..ed0bf21 100644 --- a/src/serve.ts +++ b/src/serve.ts @@ -10,7 +10,7 @@ import WebpackDevServer from 'webpack-dev-server' import { Config as ProxyConfig } from 'http-proxy-middleware' import logger from './utils/logger' import { getPageFilename, getPathFromUrl, logLifecycle, watchFile } from './utils' -import { getServeConfig } from './webpack' +import { getConfigForDevServer } from './webpack' import { BuildConfig, DevProxy, findBuildConfig, watchBuildConfig } from './utils/build-conf' import { entries, mapValues } from 'lodash' import { abs } from './utils/paths' @@ -52,7 +52,7 @@ async function serve(port: number) { async function runDevServer(port: number) { const buildConfig = await findBuildConfig() - const webpackConfig = await getServeConfig() + const webpackConfig = await getConfigForDevServer() logger.debug('webpack config:', webpackConfig) const devServerConfig: WebpackDevServer.Configuration = { diff --git a/src/utils/webpack.ts b/src/utils/webpack.ts index 3085189..5ed6fc0 100644 --- a/src/utils/webpack.ts +++ b/src/utils/webpack.ts @@ -45,7 +45,7 @@ export function adaptLoader({ loader, options }: LoaderInfo): LoaderInfo { const sourcemapParseFailedWarningPattern = /Failed to parse source map from/ /** 配置 source map */ -export function processSourceMap(config: Configuration, highQuality: boolean) { +export function processSourceMapForDevServer(config: Configuration, highQuality: boolean) { config = produce(config, (newConfig: Configuration) => { // 使用 cheap-module-source-map 而不是 eval-cheap-module-source-map 或 eval-source-map // 具体原因见 https://github.com/Front-End-Engineering-Cloud/builder/pull/139#discussion_r676475522 diff --git a/src/webpack/index.ts b/src/webpack/index.ts index f18ea13..9573f8a 100644 --- a/src/webpack/index.ts +++ b/src/webpack/index.ts @@ -1,4 +1,5 @@ import { mapValues } from 'lodash' +import produce from 'immer' import fs from 'fs' import path from 'path' import { Configuration, DefinePlugin } from 'webpack' @@ -16,7 +17,7 @@ import { addTransforms } from './transform' import { Env, getEnv } from '../utils/build-env' import logger from '../utils/logger' import { getPathFromUrl, getPageFilename } from '../utils' -import { appendPlugins, processSourceMap, appendCacheGroups, parseOptimizationConfig, enableFilesystemCache } from '../utils/webpack' +import { appendPlugins, processSourceMapForDevServer, appendCacheGroups, parseOptimizationConfig, enableFilesystemCache } from '../utils/webpack' import { svgoConfigForImagemin } from '../utils/svgo' const dirnameOfBuilder = path.resolve(__dirname, '../..') @@ -62,22 +63,21 @@ export async function getConfig(): Promise { filename: 'static/[name]-[contenthash].js', chunkFilename: 'static/[id]-[chunkhash].js', assetModuleFilename: 'static/[name]-[contenthash][ext]', - publicPath: ( - isProd - ? buildConfig.publicUrl - : getPathFromUrl(buildConfig.publicUrl) - ), + publicPath: buildConfig.publicUrl, environment: { // 这里控制 webpack 本身的运行时代码(而不是业务代码), - // 对于语言 feature 先全部配合不支持,以确保 webpack 会产出兼容性最好的代码; + // 在生产环境,对于语言 feature 先全部配置不支持,以确保 webpack 会产出兼容性最好的代码; // TODO: 后续考虑通过使用 build config 中的 targets.browsers 来挨个判断是否支持 - arrowFunction: false, - bigIntLiteral: false, + arrowFunction: isDev, + bigIntLiteral: isDev, + // 当前版本的 webpack(v5.52.0)对 const 的使用有点问题,这里如果开启 const,开发环境会报错误: + // > cannot access '__webpack_default_export__' before initialization + // 预期后边的 webpack 版本会修复这个问题,这里先关掉;升级 webpack 后 check 下这里,再打开 const: false, - destructuring: false, - dynamicImport: false, - forOf: false, - module: false + destructuring: isDev, + dynamicImport: isDev, + forOf: isDev, + module: isDev } }, optimization: { @@ -85,7 +85,8 @@ export async function getConfig(): Promise { '...', new CssMinimizerPlugin() ] - } + }, + devtool: false } let baseChunks: string[] = [] @@ -96,10 +97,6 @@ export async function getConfig(): Promise { config = appendCacheGroups(config, result.cacheGroups) } - if (isDev) { - config = processSourceMap(config, buildConfig.optimization.highQualitySourceMap) - } - config = addTransforms(config, buildConfig) const htmlPlugins = Object.entries(buildConfig.pages).map(([ name, { template, entries } ]) => { @@ -155,24 +152,40 @@ export async function getConfig(): Promise { })) } - if (isDev && buildConfig.optimization.filesystemCache) { - config = enableFilesystemCache(config) - } - return config } -/** 获取 webpack 配置(dev server 用,不含 dev server 配置) */ -export async function getServeConfig() { +/** 获取用于 dev server 的 webpack 配置(但不含对 dev server 本身的配置)*/ +export async function getConfigForDevServer() { + + let config = await getConfig() const buildConfig = await findBuildConfig() - const { errorOverlay } = buildConfig.optimization - const config = await getConfig() - return appendPlugins( - config, - new ReactFastRefreshPlugin({ - overlay: errorOverlay - }) - ) + const { filesystemCache, highQualitySourceMap, errorOverlay } = buildConfig.optimization + const isDev = getEnv() === Env.Dev + + // 只保留 publicPath 中的 path,确保静态资源请求与页面走相同的 host(即本地 dev server) + config = produce(config, newConfig => { + newConfig.output!.publicPath = getPathFromUrl(buildConfig.publicUrl) + }) + + if (isDev && filesystemCache) { + config = enableFilesystemCache(config) + } + + if (isDev) { + config = processSourceMapForDevServer(config, highQualitySourceMap) + } + + if (isDev) { + config = appendPlugins( + config, + new ReactFastRefreshPlugin({ + overlay: errorOverlay + }) + ) + } + + return config } /** 获取合适的 webpack mode */ From cbdea496da96e25ed4451d4c10ac991677061716 Mon Sep 17 00:00:00 2001 From: nighca Date: Thu, 17 Feb 2022 11:51:33 +0800 Subject: [PATCH 4/4] v2.4.0 --- npm-shrinkwrap.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 167a16d..ee62d93 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,12 +1,12 @@ { "name": "fec-builder", - "version": "2.3.0", + "version": "2.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "fec-builder", - "version": "2.3.0", + "version": "2.4.0", "dependencies": { "@babel/core": "^7.12.3", "@babel/plugin-proposal-class-properties": "^7.12.1", diff --git a/package.json b/package.json index ce421bd..43c2259 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fec-builder", - "version": "2.3.0", + "version": "2.4.0", "bin": { "fec-builder": "./lib/bin.js" },