Skip to content

Commit

Permalink
refactor: 修改 html 相关逻辑与问题
Browse files Browse the repository at this point in the history
  • Loading branch information
winixt committed Apr 5, 2022
1 parent d07416b commit 5f9d356
Show file tree
Hide file tree
Showing 27 changed files with 226 additions and 122 deletions.
1 change: 1 addition & 0 deletions docs/.vuepress/configs/sidebar/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const zh: SidebarConfig = {
'/zh/guide/plugin.md',
'/zh/guide/template.md',
'/zh/guide/mock.md',
'/zh/guide/upgrade2.1.md',
]
},
{
Expand Down
15 changes: 14 additions & 1 deletion docs/zh/guide/builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

### 配置

Webpack 和 Vite 构建在配置方面有一些差异,具体可以查阅[配置](../reference/config)
Webpack 和 Vite 构建在配置方面有一些差异,具体可以查看[配置](../reference/config)

### 静态文件处理

Expand All @@ -20,3 +20,16 @@ Webpack 和 Vite 构建在配置方面有一些差异,具体可以查阅[配
### html 模版

Webpack 对于 html 模版是没有什么限制的,而 Vite 推荐模版文件就放在项目根目录下。Webpack 有个非常强大的 [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin),Fes.js 引入了[vite-plugin-html](https://github.com/vbenjs/vite-plugin-html) 进行能力的对齐,如果开发者想要个性化定制模版,那么在配置上还是存在差异的。

## 升级 2.1.x

### 不变更构建方式

直接添加 Webpack 构建依赖包即可: `npm i @fesjs/build-webpack -D`

### 换成 Vite

1. 安装依赖包 `npm i @fesjs/build-vite`
2. 将 Webpack 相关的配置换成 Vite,具体可查看[配置](../reference/config)
3. 将 html 模版文件从 `public/index.html` 挪到项目根目录,如果有相应的 [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) 配置,需要改成 [vite-plugin-html](https://github.com/vbenjs/vite-plugin-html) 的写法。
4.`require` 等 Vite 不支持的代码,改写成 Vite 支持的方式。
68 changes: 32 additions & 36 deletions docs/zh/guide/template.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,52 @@
# HTML 模板

Fes.js 基于 [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) 实现的模板功能,默认模板内容是:
Fes.js 默认模板内容是:

```html
<!DOCTYPE html>
<html>
<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><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="app"></div>
</body>
<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><%= title %></title>
</head>
<body>
<div id="<%= mountElementId %>"></div>
</body>
</html>
```

## 自定义模板
`src/public` 文件夹中创建`index.html`,Fes.js 约定如果这个文件存在,则会替换默认模板。

## 模板配置
在配置文件(`.fes.js`)中配置 `html`,把[配置](https://github.com/jantimon/html-webpack-plugin#options)的对象作为参数传入 `html-webpack-plugin` 实例。
## 修改页面标题

举个 :chestnut:
```js
// .fes.js
export default {
html: {
title: '海贼王'
}
}
title: '这是页面标题',
};
```
页面的标题会设置成'海贼王'。

## 模板变量
当然我们也可以手动编写模板,在模板中添加`link``link``meta`等标签。在我们手动配置模板时,有时候需要用到一些环境变量,模板里可以获取到的变量如下:
页面的标题会设置成 `这是页面标题`

- **htmlWebpackPlugin**,特定于此插件的数据
- **webpackConfig**,用于此编译的webpack配置。例如,它可用于获取publicPath(webpackConfig.output.publicPath)。
- **compilation**,webpack编译对象。例如,可以使用它来获取已处理资产的内容,并将其直接内联到页面中compilation.assets[...].source()
## 模板变量

举个 🌰 :
```html
<link rel="icon" type="image/x-icon" href="<%= webpackConfig.output.publicPath %>favicon.png" />
```
模版中可以使用的变量:

除上述 `html-webpack-plugin` 插件提供的变量外,Fes.js 还把 `process.env` 中的环境变量添加到模板作用域内:
- `NODE_ENV`
- `FES_ENV`
- `.env` 文件中以 `FES_APP_` 开头的变量
- `NODE_ENV`: Node.js 环境变量
- `FES_ENV`: Fes.js 环境变量
- `BASE_URL`: publicPath
- `.env.**`: 文件中以 `FES_APP_` 开头的变量

举个 🌰 :

```env
# .env
FES_APP_HELLO_WORLD=hello world
```

```html
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
```
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<body>
<div><%= FES_APP_HELLO_WORLD %></div>
</body>
```
22 changes: 22 additions & 0 deletions docs/zh/guide/upgrade2.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# 从 2.0.x 迁移到 2.1.x

## 版本 2.1.x 的 break

1. 编译时的 [base](../reference/config/#base) 配置,移到了 [router.base](../reference/config/#router)

## 相关插件

由于需要兼容 Vite 的写法,插件也做了相关代码调整,

## 不变更构建方式

1. 添加 Webpack 构建依赖包: `npm i @fesjs/build-webpack -D`
2. 如果有,将 `public/index.html` 文件挪到项目根目录,移除 [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) 相关配置,具体模版变量使用请查看[HTML 模版](../guide/template.html)

## 换成 Vite

1. 安装依赖包 `npm i @fesjs/build-vite`
2. 将 Webpack 相关的配置换成 Vite,具体可查看[配置](../reference/config)
3. 将 html 模版文件从 `public/index.html` 挪到项目根目录,如果有相应的 [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) 配置,需要改成 [vite-plugin-html](https://github.com/vbenjs/vite-plugin-html) 的写法。
4.`require` 等 Vite 不支持的代码,改写成 Vite 支持的方式。
5. 由于需要兼容 Vite 写法,相关插件也做了相关调整,因此依赖的插件都需要升级最新的版本。如果用了 [@fesjs/plugin-sass](../reference/plugin/plugins/sass.html) 插件,直接移除,手动安装 `sass` 依赖即可。
9 changes: 8 additions & 1 deletion docs/zh/reference/config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ export default {
### router

- 类型: `object`
- 默认值: `{ mode: 'hash' }`
- 默认值: `{ mode: 'hash', base: '/' }`
- 详情:

配置路由,具体请查看指南中关于路由的介绍
Expand Down Expand Up @@ -282,6 +282,13 @@ const defaultTerserOptions = {

配置 [压缩器 terser 的配置项](https://github.com/terser/terser#minify-options)

### title

- 类型: `string`
- 详情:

html 页面标题

## webpack 专属配置

### analyze
Expand Down
6 changes: 0 additions & 6 deletions packages/fes-build-vite/src/commands/dev/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { createServer } from 'vite';
import getDevConfig from './getDevConfig';

/**
* TODO
*
* 共享 webpack 和 vite 的部分配置,降低熟悉 vite 的成本
*/

export default (api) => {
const {
paths,
Expand Down
1 change: 1 addition & 0 deletions packages/fes-build-vite/src/common/getConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export function getInnerCommonConfig(api) {
inject: {
data: {
...resolveRuntimeEnv(publicPath),
title: api.config.title || 'Fes.js',
mountElementId: api.config.mountElementId,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import { winPath, resolveRuntimeEnv } from '@fesjs/utils';

export default async function createHtmlWebpackConfig({ api, cwd, config, webpackConfig, headScripts, isProd, publicPath }) {
const htmlOptions = {
title: 'fes.js',
filename: '[name].html',
...config.html,
templateParameters: resolveRuntimeEnv(publicPath),
mountElementId: config.mountElementId,
templateParameters: {
title: config.html?.title || api.config.title || 'Fes.js',
...resolveRuntimeEnv(publicPath),
mountElementId: config.mountElementId,
},
};

if (isProd) {
Expand All @@ -24,7 +26,7 @@ export default async function createHtmlWebpackConfig({ api, cwd, config, webpac
});
}

const htmlPath = join(cwd, 'public/index.html');
const htmlPath = join(cwd, 'index.html');
const defaultHtmlPath = resolve(__dirname, 'index-default.html');
const publicCopyIgnore = [];

Expand All @@ -45,10 +47,12 @@ export default async function createHtmlWebpackConfig({ api, cwd, config, webpac
if (_fileName !== 'index.html') {
const _htmlOptions = {
...config.html,
title: route?.meta?.title || config.html.title || 'fes.js',
filename: _fileName,
templateParameters: resolveRuntimeEnv(publicPath),
mountElementId: config.mountElementId,
templateParameters: {
title: route?.meta?.title || config.html.title || api.config.title || 'fes.js',
...resolveRuntimeEnv(publicPath),
mountElementId: config.mountElementId,
},
};
webpackConfig.plugin(_fileName).use(require.resolve('html-webpack-plugin'), [_htmlOptions]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>
<%= htmlWebpackPlugin.options.title %>
<%= title %>
</title>
</head>

<body>
<div id="<%= htmlWebpackPlugin.options.mountElementId %>"></div>
<div id="<%= mountElementId %>"></div>
</body>

</html>
2 changes: 2 additions & 0 deletions packages/fes-plugin-windicss/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
"vue": "^3.0.5"
},
"dependencies": {
"vite-plugin-windicss": "^1.8.3",
"windicss": "^3.5.1",
"windicss-webpack-plugin": "^1.6.0"
},
"typings": "./types.d.ts"
Expand Down
68 changes: 43 additions & 25 deletions packages/fes-plugin-windicss/src/index.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,25 @@
import WindiCSSWebpackPlugin from 'windicss-webpack-plugin';
import WindiCSS from 'vite-plugin-windicss';
import { name } from '../package.json';

export default (api) => {
api.describe({
key: 'windicss',
function getWindicssConfig(api) {
const { config, ...otherOption } = api.config.windicss;
return {
config: {
schema(joi) {
return joi.object();
extract: {
// A common use case is scanning files from the root directory
include: ['**/*.{vue,jsx,js,ts,tsx}'],
// if you are excluding files, make sure you always include node_modules and .git
exclude: ['node_modules', '.git', 'dist', '.fes'],
},
default: {},
...config,
},
});

api.addEntryImportsAhead(() => [{ source: 'windi-base.css' }, { source: 'windi-components.css' }, { source: 'windi-utilities.css' }]);
...otherOption,
};
}

function buildWindicssWithWebpack(api) {
api.chainWebpack((memo, { createCSSRule }) => {
const { config, ...otherOption } = api.config.windicss;
memo.plugin('windicss').use(WindiCSSWebpackPlugin, [
{
config: {
extract: {
// A common use case is scanning files from the root directory
include: ['**/*.{vue,jsx,js,ts,tsx}'],
// if you are excluding files, make sure you always include node_modules and .git
exclude: ['node_modules', '.git', 'dist', '.fes'],
},
...config,
},
...otherOption,
},
]);
memo.plugin('windicss').use(require('windicss-webpack-plugin'), [getWindicssConfig(api)]);
if (api.env === 'development') {
memo.module.rule('css').test((path) => {
if (path.endsWith('windi-utilities.css')) {
Expand All @@ -48,6 +38,34 @@ export default (api) => {

return memo;
});
}

function buildWindicssWithVite(api) {
api.modifyBundleConfig((memo) => {
memo.plugins.push(WindiCSS(getWindicssConfig(api).config));

return memo;
});
}

export default (api) => {
api.describe({
key: 'windicss',
config: {
schema(joi) {
return joi.object();
},
default: {},
},
});

api.addEntryImportsAhead(() => [{ source: 'windi-base.css' }, { source: 'windi-components.css' }, { source: 'windi-utilities.css' }]);

if (api.builder.isVite) {
buildWindicssWithVite(api);
} else {
buildWindicssWithWebpack(api);
}

api.addConfigType(() => ({
source: name,
Expand Down
1 change: 1 addition & 0 deletions packages/fes-preset-built-in/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default function () {
require.resolve('./plugins/features/singular'),
require.resolve('./plugins/features/targets'),
require.resolve('./plugins/features/terserOptions'),
require.resolve('./plugins/features/title'),

// route
require.resolve('./plugins/route'),
Expand Down
3 changes: 2 additions & 1 deletion packages/fes-preset-built-in/src/plugins/features/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { extname } from 'path';
import historyFallback from 'connect-history-api-fallback';

const ASSET_EXT_NAMES = ['.ico', '.png', '.jpg', '.jpeg', '.gif', '.svg'];
const SKIP_PATHS_PREFIX = ['/@vite', '/@id'];
const SKIP_PATHS_PREFIX = ['/@'];

const proxyMiddleware = (api) => (req, res, next) => {
const proxyConfig = api.config.proxy;
Expand All @@ -15,6 +15,7 @@ const proxyMiddleware = (api) => (req, res, next) => {
if (ASSET_EXT_NAMES.includes(extname(req.url))) {
return next();
}

const history = historyFallback();
history(req, res, next);
};
Expand Down
10 changes: 10 additions & 0 deletions packages/fes-preset-built-in/src/plugins/features/title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default (api) => {
api.describe({
key: 'title',
config: {
schema(joi) {
return joi.string();
},
},
});
};
Loading

0 comments on commit 5f9d356

Please sign in to comment.