Compare commits

...

8 Commits

Author SHA1 Message Date
neverland
154408fa8b
perf: remove less source file to remove bundle size (#10752)
* perf: remove css source file to remove bundle size

* docs: update migration guide
2022-06-26 21:52:40 +08:00
chenjiahan
20ee462cab Merge branch 'dev' into next 2022-06-26 21:43:49 +08:00
neverland
293dab6a51
feat(cli): add build.bundleOptions config (#10751) 2022-06-26 21:42:28 +08:00
neverland
bb23e1b700
feat(cli): add css.removeSourceFile config (#10750) 2022-06-26 17:15:11 +08:00
chenjiahan
2b77f96fc5 Merge branch 'dev' into next 2022-06-25 12:48:53 +08:00
AmazingPromise
e61d85a890 fix(List): element with overflow: overlay style should be considered a scroll container (#10743) 2022-06-25 12:36:27 +08:00
neverland
2c2cdd077f
chore(cli): remove unused ssr.js (#10729) 2022-06-19 16:04:10 +08:00
neverland
c83a57b2bd
docs: add guide of function component style (#10728) 2022-06-19 15:34:00 +08:00
11 changed files with 206 additions and 64 deletions

View File

@ -103,7 +103,7 @@ module.exports = {
- Type: `string`
- Default: `'less'`
CSS preprocess Config, support `less` and `sass`. Use `less` by default.
CSS preprocessor config, support `less` and `sass`. Use `less` by default.
```js
module.exports = {
@ -115,6 +115,23 @@ module.exports = {
};
```
### build.css.removeSourceFile
- Type: `boolean`
- Default: `'false'`
Whether to remove the source style files after build.
```js
module.exports = {
build: {
css: {
removeSourceFile: true,
},
},
};
```
### build.site.publicPath
- Type: `string`
@ -204,6 +221,45 @@ module.exports = {
`npm` package manager.
### build.bundleOptions
- Type: `BundleOptions[]`
Specify the format of the bundled output.
The type of `BundleOptions`:
```ts
type BundleOption = {
// Whether to minify code (Tips: es format output can't be minified by vite)
minify?: boolean;
// Formats, can be set to 'es' | 'cjs' | 'umd' | 'iife'
formats: LibraryFormats[];
// Dependencies to external (Vue is externaled by default)
external?: string[];
};
```
Default value
```ts
const DEFAULT_OPTIONS: BundleOption[] = [
{
minify: false,
formats: ['umd'],
},
{
minify: true,
formats: ['umd'],
},
{
minify: false,
formats: ['es', 'cjs'],
external: allDependencies,
},
];
```
### site.title
- Type: `string`

View File

@ -115,6 +115,23 @@ module.exports = {
};
```
### build.css.removeSourceFile
- Type: `boolean`
- Default: `'false'`
是否在构建后移除样式文件的源代码。
```js
module.exports = {
build: {
css: {
removeSourceFile: true,
},
},
};
```
### build.site.publicPath
- Type: `string`
@ -206,6 +223,45 @@ module.exports = {
指定使用的包管理器。
### build.bundleOptions
- Type: `BundleOptions[]`
指定打包后产物的格式。
产物格式由三个配置项控制:
```ts
type BundleOption = {
// 是否压缩代码(注意 es 产物无法被 vite 压缩)
minify?: boolean;
// 产物类型,可选值为 'es' | 'cjs' | 'umd' | 'iife'
formats: LibraryFormats[];
// 需要 external 的依赖Vue 默认会被 external
external?: string[];
};
```
该选项的默认值为:
```ts
const DEFAULT_OPTIONS: BundleOption[] = [
{
minify: false,
formats: ['umd'],
},
{
minify: true,
formats: ['umd'],
},
{
minify: false,
formats: ['es', 'cjs'],
external: allDependencies,
},
];
```
### site.title
- Type: `string`

View File

@ -1,68 +1,41 @@
import fse from 'fs-extra';
import { join } from 'path';
import { build } from 'vite';
import { getPackageJson, getVantConfig, LIB_DIR } from '../common/constant.js';
import { getPackageJson, getVantConfig } from '../common/constant.js';
import { mergeCustomViteConfig } from '../common/index.js';
import { getViteConfigForPackage } from '../config/vite.package.js';
import type { LibraryFormats } from 'vite';
// generate entry file for nuxt
async function genEntryForSSR() {
const { name } = getVantConfig();
const cjsPath = join(LIB_DIR, 'ssr.js');
const mjsPath = join(LIB_DIR, 'ssr.mjs');
const cjsContent = `'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./${name}.cjs.min.js');
} else {
module.exports = require('./${name}.cjs.js');
export type BundleOption = {
minify?: boolean;
formats: LibraryFormats[];
external?: string[];
};
`;
const mjsContent = `export * from './index.js';\n`;
return Promise.all([
fse.outputFile(cjsPath, cjsContent),
fse.outputFile(mjsPath, mjsContent),
]);
}
export async function compileBundles() {
const dependencies = getPackageJson().dependencies || {};
const externals = Object.keys(dependencies);
const external = Object.keys(dependencies);
const configs = [
// umd bundle
getViteConfigForPackage({
const DEFAULT_OPTIONS: BundleOption[] = [
{
minify: false,
formats: ['umd'],
external: ['vue'],
}),
// umd bundle (minified)
getViteConfigForPackage({
},
{
minify: true,
formats: ['umd'],
external: ['vue'],
}),
// esm/cjs bundle
getViteConfigForPackage({
},
{
minify: false,
formats: ['es', 'cjs'],
external: ['vue', ...externals],
}),
// esm/cjs bundle (minified)
// vite will not minify es bundle
// see: https://github.com/vuejs/vue-next/issues/2860
getViteConfigForPackage({
minify: true,
formats: ['es', 'cjs'],
external: ['vue', ...externals],
}),
external,
},
];
const bundleOptions: BundleOption[] =
getVantConfig().build?.bundleOptions || DEFAULT_OPTIONS;
await Promise.all(
configs.map((config) => build(mergeCustomViteConfig(config)))
bundleOptions.map((config) =>
build(mergeCustomViteConfig(getViteConfigForPackage(config)))
)
);
await genEntryForSSR();
}

View File

@ -1,11 +1,13 @@
import { parse } from 'path';
import { readFileSync, writeFileSync } from 'fs';
import { replaceExt } from '../common/index.js';
import fse from 'fs-extra';
import { getVantConfig, replaceExt } from '../common/index.js';
import { compileCss } from './compile-css.js';
import { compileLess } from './compile-less.js';
import { compileSass } from './compile-sass.js';
import { consola } from '../common/logger.js';
const { readFileSync, writeFileSync, removeSync } = fse;
async function compileFile(filePath: string) {
const parsedPath = parse(filePath);
@ -30,6 +32,11 @@ async function compileFile(filePath: string) {
export async function compileStyle(filePath: string) {
const css = await compileFile(filePath);
const vantConfig = getVantConfig();
if (vantConfig.build?.css?.removeSourceFile) {
removeSync(filePath);
}
writeFileSync(replaceExt(filePath, '.css'), css);
}

View File

@ -12,6 +12,7 @@ import {
ES_DIR,
SRC_DIR,
LIB_DIR,
getVantConfig,
STYLE_DEPS_JSON_FILE,
} from '../common/constant.js';
@ -87,8 +88,10 @@ export function genComponentStyle(
delete require.cache[STYLE_DEPS_JSON_FILE];
}
const vantConfig = getVantConfig();
const components = getComponents();
const baseFile = getCssBaseFile();
const hasSourceFile = vantConfig.build?.css?.removeSourceFile !== true;
components.forEach((component) => {
genEntry({
@ -98,7 +101,7 @@ export function genComponentStyle(
ext: '.css',
});
if (CSS_LANG !== 'css') {
if (CSS_LANG !== 'css' && hasSourceFile) {
genEntry({
baseFile,
component,

View File

@ -1,17 +1,14 @@
import { join } from 'path';
import { setBuildTarget } from '../common/index.js';
import { CWD, ES_DIR, getVantConfig, LIB_DIR } from '../common/constant.js';
import type { InlineConfig, LibraryFormats } from 'vite';
import type { InlineConfig } from 'vite';
import type { BundleOption } from '../compiler/compile-bundles.js';
export function getViteConfigForPackage({
minify,
formats,
external,
}: {
minify: boolean;
formats: LibraryFormats[];
external: string[];
}): InlineConfig {
external = [],
}: BundleOption): InlineConfig {
setBuildTarget('package');
const { name, build } = getVantConfig();
@ -36,7 +33,7 @@ export function getViteConfigForPackage({
// terser has better compression than esbuild
minify: minify ? 'terser' : false,
rollupOptions: {
external,
external: [...external, 'vue'],
output: {
dir: LIB_DIR,
exports: 'named',

View File

@ -3,7 +3,7 @@ import { inBrowser } from '../utils';
type ScrollElement = HTMLElement | Window;
const overflowScrollReg = /scroll|auto/i;
const overflowScrollReg = /scroll|auto|overlay/i;
const defaultRoot = inBrowser ? window : undefined;
function isElement(node: Element) {

View File

@ -112,6 +112,8 @@ emit('clickInput');
目前 Vant 已经支持了基于 CSS 变量的主题定制能力,因此后续将不再提供基于 Less 的主题定制方式。
这意味着 Vant 的 npm 包中将不再会包含 `.less` 样式源文件,只会提供编译后的 `.css` 样式文件。
如果你的项目正在使用旧版的 Less 主题定制,请使用 [ConfigProvider 全局配置](#/zh-CN/config-provider) 组件进行替换。
### 简化 CSS 变量名

View File

@ -172,6 +172,28 @@ const app = createApp();
app.use(Button);
```
#### 4. Style of Function Components
Some components of Vant are provided as function, including `Toast`, `Dialog`, `Notify` and `ImagePreview`. When using function components, `unplugin-vue-components` can not auto import the component style, so we need to import style manually.
```js
// Toast
import { Toast } from 'vant';
import 'vant/es/toast/style';
// Dialog
import { Dialog } from 'vant';
import 'vant/es/dialog/style';
// Notify
import { Notify } from 'vant';
import 'vant/es/notify/style';
// ImagePreview
import { ImagePreview } from 'vant';
import 'vant/es/image-preview/style';
```
> Vant supports tree shaking by default, so you don't necessarily need the webpack plugin, if you can't accept the full import of css.
### Import all components (not recommended)

View File

@ -173,7 +173,29 @@ const app = createApp();
app.use(Button);
```
> 注意Vant 默认支持通过 Tree Shaking因此你也可以不配置任何插件直接通过 Tree Shaking 来移除不需要的 JS 代码,但 CSS 无法通过这种方式优化。
#### 4. 引入函数组件的样式
Vant 中有个别组件是以函数的形式提供的,包括 `Toast``Dialog``Notify``ImagePreview` 组件。在使用函数组件时,`unplugin-vue-components` 无法自动引入对应的样式,因此需要手动引入样式。
```js
// Toast
import { Toast } from 'vant';
import 'vant/es/toast/style';
// Dialog
import { Dialog } from 'vant';
import 'vant/es/dialog/style';
// Notify
import { Notify } from 'vant';
import 'vant/es/notify/style';
// ImagePreview
import { ImagePreview } from 'vant';
import 'vant/es/image-preview/style';
```
> 注意Vant 支持 Tree Shaking因此你也可以不配置任何插件通过 Tree Shaking 即可移除不需要的 JS 代码,但 CSS 无法通过这种方式优化。
### 导入所有组件(不推荐)

View File

@ -6,15 +6,19 @@ export default {
skipInstall: ['lazyload'],
packageManager: 'pnpm',
extensions: {
esm: '.mjs'
esm: '.mjs',
},
site: {
publicPath:
(typeof window === 'undefined' && process.env.PUBLIC_PATH) || '/vant/v4',
(typeof window === 'undefined' && process.env.PUBLIC_PATH) ||
'/vant/v4',
},
vetur: {
tagPrefix: 'van-',
},
css: {
removeSourceFile: true,
},
},
site: {
defaultLang: 'en-US',