diff --git a/docs/faq/README.md b/docs/faq/README.md index a01d1b4..0903f6f 100644 --- a/docs/faq/README.md +++ b/docs/faq/README.md @@ -116,6 +116,215 @@ You need to set your publicPath configuration to an absolute url, and in develop } ``` +### After the micro-app is bundled, the font files and images in the css load 404 + +The reason is that `qiankun` changed the external link style to the inline style, but the loading path of the font file and background image is a relative path. + +Once the `css` file is packaged, you cannot modify the path of the font file and background image by dynamically modifying the `publicPath`. + +There are mainly the following solutions: + +1. Upload all static resources such as pictures to `cdn`, and directly reference the address of `cdn` in `css` (**recommended**) + +2. Use the `url-loader` of `webpack` to package font files and images as `base64` (suitable for projects with small font files and images)(**recommended**) + + ```js + module.exports = { + module: { + rules: [ + { + test: /\.(png|jpe?g|gif|webp|woff2?|eot|ttf|otf)$/i, + use: [ + { + loader: 'url-loader', + options: {}, + }, + ], + }, + ], + }, + }; + ``` + + `vue-cli3` project: + + ```js + module.exports = { + chainWebpack: (config) => { + config.module + .rule('fonts') + .use('url-loader') + .loader('url-loader') + .options({}) + .end() + config.module + .rule('images') + .use('url-loader') + .loader('url-loader') + .options({}) + .end() + }, + } + +3. Use the `file-loader` of `webpack` to inject the full path when packaging it (suitable for projects with large font files and images) + + ```js + const publicPath = process.env.NODE_ENV === "production" ? 'https://qiankun.umijs.org/' : `http://localhost:${port}`; + module.exports = { + module: { + rules: [ + { + test: /\.(png|jpe?g|gif|webp)$/i, + use: [ + { + loader: 'file-loader', + options: { + name: 'img/[name].[hash:8].[ext]', + publicPath + }, + }, + ], + }, + { + test: /\.(woff2?|eot|ttf|otf)$/i, + use: [ + { + loader: 'file-loader', + options: { + name: 'fonts/[name].[hash:8].[ext]', + publicPath + }, + }, + ], + }, + ], + }, + }; + ``` + + `vue-cli3` project: + + ```js + const publicPath = process.env.NODE_ENV === "production" ? 'https://qiankun.umijs.org/' : `http://localhost:${port}`; + module.exports = { + chainWebpack: (config) => { + const fontRule = config.module.rule('fonts'); + fontRule.uses.clear(); + fontRule + .use('file-loader') + .loader('file-loader') + .options({ + name: 'fonts/[name].[hash:8].[ext]', + publicPath + }) + .end() + const imgRule = config.module.rule('images'); + imgRule.uses.clear(); + imgRule + .use('file-loader') + .loader('file-loader') + .options({ + name: 'img/[name].[hash:8].[ext]', + publicPath + }) + .end() + }, + } + ``` + +4. Combine the two schemes, convert small files to `base64`, and inject path prefixes for large files + + ```js + const publicPath = process.env.NODE_ENV === "production" ? 'https://qiankun.umijs.org/' : `http://localhost:${port}`; + module.exports = { + module: { + rules: [ + { + test: /\.(png|jpe?g|gif|webp)$/i, + use: [ + { + loader: 'url-loader', + options: {}, + fallback: { + loader: 'file-loader', + options: { + name: 'img/[name].[hash:8].[ext]', + publicPath + } + } + }, + ], + }, + { + test: /\.(woff2?|eot|ttf|otf)$/i, + use: [ + { + loader: 'url-loader', + options: {}, + fallback: { + loader: 'file-loader', + options: { + name: 'fonts/[name].[hash:8].[ext]', + publicPath + } + } + }, + ], + }, + ], + }, + }; + ``` + + `vue-cli3` project: + + ```js + const publicPath = process.env.NODE_ENV === "production" ? 'https://qiankun.umijs.org/' : `http://localhost:${port}`; + module.exports = { + chainWebpack: (config) => { + config.module.rule('fonts') + .use('url-loader') + .loader('url-loader') + .options({ + limit: 4096, // Less than 4kb will be packaged as base64 + fallback: { + loader: 'file-loader', + options: { + name: 'fonts/[name].[hash:8].[ext]', + publicPath + } + } + }) + .end(); + config.module.rule('images') + .use('url-loader') + .loader('url-loader') + .options({ + limit: 4096, // Less than 4kb will be packaged as base64 + fallback: { + loader: 'file-loader', + options: { + name: 'img/[name].[hash:8].[ext]', + publicPath + } + } + }) + }, + } + ``` + +5. The `vue-cli3` project can package `css` into `js` without generating files separately (not recommended, only suitable for projects with less `css`) + + Configuration reference [vue-cli3 official website](https://cli.vuejs.org/zh/config/#css-extract): + + ```js + module.exports = { + css: { + extract: false + }, + } + ``` + ## Must a sub app asset support cors? Yes it is. @@ -315,29 +524,6 @@ location = /index.html { } ``` -## Font file loading error after micro application packaging - -The reason is that `qiankun` changed the external link style to the inline style, but the loading path of the font file is a relative path. - -Modify the `webpack` package and inject the path prefix to the font file: - -```js -module.exports = { - chainWebpack: (config) => { - config.module - .rule('fonts') - .test(/.(ttf|otf|eot|woff|woff2)$/) - .use('url-loader') - .loader('url-loader') - .tap(options => ({ - name:'/fonts/[name].[hash:8].[ext]', - limit: 4096, // Fonts smaller than 4KB will be packaged as base64 - })) - .end() - }, -} -``` - ## micro app styles was lost when using config entry Some scenarios we had to use config entry to load micro app (** not recommended **): diff --git a/docs/faq/README.zh.md b/docs/faq/README.zh.md index e32ae46..c21ef9d 100644 --- a/docs/faq/README.zh.md +++ b/docs/faq/README.zh.md @@ -118,6 +118,216 @@ runtime publicPath 主要解决的是微应用动态载入的 脚本、样式、 } ``` +### 微应用打包之后 css 中的字体文件和图片加载 404 + +原因是 `qiankun` 将外链样式改成了内联样式,但是字体文件和背景图片的加载路径是相对路径。 + +而 `css` 文件一旦打包完成,就无法通过动态修改 `publicPath` 来修正其中的字体文件和背景图片的路径。 + +主要有以下几个解决方案: + +1. 所有图片等静态资源上传至 `cdn`,`css` 中直接引用 `cdn` 地址(**推荐**) + +2. 借助 `webpack` 的 `url-loader` 将字体文件和图片打包成 `base64`(适用于字体文件和图片体积小的项目)(**推荐**) + + ```js + module.exports = { + module: { + rules: [ + { + test: /\.(png|jpe?g|gif|webp|woff2?|eot|ttf|otf)$/i, + use: [ + { + loader: 'url-loader', + options: {}, + }, + ], + }, + ], + }, + }; + ``` + + `vue-cli3` 项目写法: + + ```js + module.exports = { + chainWebpack: (config) => { + config.module + .rule('fonts') + .use('url-loader') + .loader('url-loader') + .options({}) + .end() + config.module + .rule('images') + .use('url-loader') + .loader('url-loader') + .options({}) + .end() + }, + } + ``` + +3. 借助 `webpack` 的 `file-loader` ,在打包时给其注入完整路径(适用于字体文件和图片体积比较大的项目) + + ```js + const publicPath = process.env.NODE_ENV === "production" ? 'https://qiankun.umijs.org/' : `http://localhost:${port}`; + module.exports = { + module: { + rules: [ + { + test: /\.(png|jpe?g|gif|webp)$/i, + use: [ + { + loader: 'file-loader', + options: { + name: 'img/[name].[hash:8].[ext]', + publicPath + }, + }, + ], + }, + { + test: /\.(woff2?|eot|ttf|otf)$/i, + use: [ + { + loader: 'file-loader', + options: { + name: 'fonts/[name].[hash:8].[ext]', + publicPath + }, + }, + ], + }, + ], + }, + }; + ``` + + `vue-cli3` 项目写法: + + ```js + const publicPath = process.env.NODE_ENV === "production" ? 'https://qiankun.umijs.org/' : `http://localhost:${port}`; + module.exports = { + chainWebpack: (config) => { + const fontRule = config.module.rule('fonts'); + fontRule.uses.clear(); + fontRule + .use('file-loader') + .loader('file-loader') + .options({ + name: 'fonts/[name].[hash:8].[ext]', + publicPath + }) + .end() + const imgRule = config.module.rule('images'); + imgRule.uses.clear(); + imgRule + .use('file-loader') + .loader('file-loader') + .options({ + name: 'img/[name].[hash:8].[ext]', + publicPath + }) + .end() + }, + } + ``` + +4. 将两种方案结合起来,小文件转 `base64` ,大文件注入路径前缀 + + ```js + const publicPath = process.env.NODE_ENV === "production" ? 'https://qiankun.umijs.org/' : `http://localhost:${port}`; + module.exports = { + module: { + rules: [ + { + test: /\.(png|jpe?g|gif|webp)$/i, + use: [ + { + loader: 'url-loader', + options: {}, + fallback: { + loader: 'file-loader', + options: { + name: 'img/[name].[hash:8].[ext]', + publicPath + } + } + }, + ], + }, + { + test: /\.(woff2?|eot|ttf|otf)$/i, + use: [ + { + loader: 'url-loader', + options: {}, + fallback: { + loader: 'file-loader', + options: { + name: 'fonts/[name].[hash:8].[ext]', + publicPath + } + } + }, + ], + }, + ], + }, + }; + ``` + + `vue-cli3` 项目写法: + + ```js + const publicPath = process.env.NODE_ENV === "production" ? 'https://qiankun.umijs.org/' : `http://localhost:${port}`; + module.exports = { + chainWebpack: (config) => { + config.module.rule('fonts') + .use('url-loader') + .loader('url-loader') + .options({ + limit: 4096, // 小于4kb将会被打包成 base64 + fallback: { + loader: 'file-loader', + options: { + name: 'fonts/[name].[hash:8].[ext]', + publicPath + } + } + }) + .end(); + config.module.rule('images') + .use('url-loader') + .loader('url-loader') + .options({ + limit: 4096, // 小于4kb将会被打包成 base64 + fallback: { + loader: 'file-loader', + options: { + name: 'img/[name].[hash:8].[ext]', + publicPath + } + } + }) + }, + } + ``` + +5. `vue-cli3` 项目可以将 `css` 打包到 `js`里面,不单独生成文件(不推荐,仅适用于 `css` 较少的项目) + + 配置参考 [vue-cli3 官网](https://cli.vuejs.org/zh/config/#css-extract): + + ```js + module.exports = { + css: { + extract: false + }, + } + ``` + ## 微应用静态资源一定要支持跨域吗? 是的。 @@ -385,29 +595,6 @@ location = /index.html { } ``` -## 微应用打包之后字体文件加载出错 - -原因是 `qiankun` 将外链样式改成了内联样式,但是字体文件的加载路径是相对路径。 - -修改一下 `webpack` 打包,给字体文件注入路径前缀即可: - -```js -module.exports = { - chainWebpack: (config) => { - config.module - .rule('fonts') - .test(/.(ttf|otf|eot|woff|woff2)$/) - .use('url-loader') - .loader('url-loader') - .tap(options => ({ - name: '/fonts/[name].[hash:8].[ext]', - limit: 4096, // 小于4KB的字体将会被打包成 base64 - })) - .end() - }, -} -``` - ## 使用 config entry 时微应用样式丢失 有些场景下我们会使用 config entry 的方式加载微应用(**不推荐**):