Compare commits

..

10 Commits

Author SHA1 Message Date
chenjiahan
d8afff078a docs(@vant/cli): changelog v3.10.0 2021-04-10 17:09:22 +08:00
chenjiahan
deb30d9683 chore: release @vant/cli@3.10.0 2021-04-10 17:06:46 +08:00
neverland
16ff1ba9a7
feat(cli): support custom simulator (#8499) 2021-04-10 17:01:09 +08:00
neverland
3ddfe3bbb4
fix(cli): failed to sync route (#8498) 2021-04-10 16:02:40 +08:00
chenjiahan
5fe263b601 chore: release @vant/cli@3.9.4-beta.0 2021-04-10 15:45:45 +08:00
neverland
f46f59fce2
feat(cli): using postmessage (#8497)
* feat(cli): export action functions

* fix: listenToSyncPath

* fix: config.site.simulatorUrl
2021-04-10 15:44:55 +08:00
neverland
a066e3a4bb
chore(cli): imporve resolve path (#8496) 2021-04-10 14:53:34 +08:00
chenjiahan
d7bb080805 docs(@vant/cli): changelog 3.9.3 2021-04-10 11:52:37 +08:00
chenjiahan
9c03f86088 chore: release @vant/cli@3.9.3 2021-04-10 11:50:52 +08:00
neverland
9bb19819a5
feat(cli): add namedExport option (#8495)
* feat(cli): add exportMode option

* feat(cli): rename exportMode to namedExport
2021-04-10 11:44:02 +08:00
18 changed files with 282 additions and 138 deletions

View File

@ -60,7 +60,7 @@
"vue": "^3.0.0"
},
"devDependencies": {
"@vant/cli": "^3.9.2",
"@vant/cli": "^3.10.0",
"@vant/area-data": "^1.0.0",
"@vue/compiler-sfc": "^3.0.6",
"prettier": "2.1.0",

View File

@ -1,5 +1,18 @@
# 更新日志
## v3.10.0
`2021-04-10`
- 新增 `site.simulator` 选项
- 支持 iframe 通信跨域
## v3.9.3
`2021-04-10`
- 新增 `build.namedExport` 选项
## v3.9.2
`2021-04-04`

View File

@ -5,6 +5,8 @@
- [name](#name)
- [build.css](#buildcss)
- [build.site](#buildsite)
- [build.srcDir](#buildsrcdir)
- [build.namedExport](#buildnamedexport)
- [site.title](#sitetitle)
- [site.logo](#sitelogo)
- [site.description](#sitedescription)
@ -13,6 +15,7 @@
- [site.baiduAnalytics](#sitebaiduanalytics)
- [site.searchConfig](#sitesearchconfig)
- [site.hideSimulator](#sitehidesimulator)
- [site.simulator.url](#sitesimulatorurl)
- [Webpack](#webpack)
- [Babel](#babel)
- [默认配置](#-1)
@ -124,6 +127,17 @@ module.exports = {
};
```
### build.namedExport
- Type: `boolean`
- Default: `false`
是否通过 Named Export 对组件进行导出。
未开启此选项时,会通过 `export default from 'xxx'` 导出组件内部的默认模块。
开启此选项后,会通过 `export * from 'xxx'` 导出组件内部的所有模块、类型定义。
### site.title
- Type: `string`
@ -232,6 +246,13 @@ module.exports = {
是否隐藏所有页面右侧的手机模拟器,默认不隐藏
### site.simulator.url
- Type: `string`
- Default: -
自定义手机模拟器的 iframe URL 地址。
### site.htmlPluginOptions
- Type: `object`

View File

@ -1,10 +1,10 @@
{
"name": "@vant/cli",
"version": "3.9.2",
"version": "3.10.0",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"bin": {
"vant-cli": "./lib/index.js"
"vant-cli": "./lib/bin.js"
},
"engines": {
"node": ">=10"

View File

@ -2,28 +2,76 @@
* 同步父窗口和 iframe vue-router 状态
*/
import { iframeReady, isMobile } from '.';
import { config } from 'site-desktop-shared';
window.syncPath = function() {
const router = window.vueRouter;
const isInIframe = window !== window.top;
const currentDir = router.currentRoute.value.path;
let queue = [];
let isIframeReady = false;
if (isInIframe) {
window.top.replacePath(currentDir);
} else if (!isMobile) {
const iframe = document.querySelector('iframe');
if (iframe) {
iframeReady(iframe, () => {
iframe.contentWindow.replacePath(currentDir);
});
function iframeReady(callback) {
if (isIframeReady) {
callback();
} else {
queue.push(callback);
}
}
if (window.top === window) {
window.addEventListener('message', (event) => {
if (event.data.type === 'iframeReady') {
isIframeReady = true;
queue.forEach((callback) => callback());
queue = [];
}
}
};
});
} else {
window.top.postMessage({ type: 'iframeReady' }, '*');
}
window.replacePath = function(path = '') {
// should preserve hash for anchor
if (window.vueRouter.currentRoute.value.path !== path) {
window.vueRouter.replace(path).catch(() => {});
function getCurrentDir() {
const router = window.vueRouter;
const { path } = router.currentRoute.value;
if (config.site.simulator?.routeMapper) {
return config.site.simulator?.routeMapper(path);
}
};
return path;
}
export function syncPathToParent() {
window.top.postMessage(
{
type: 'replacePath',
value: getCurrentDir(),
},
'*'
);
}
export function syncPathToChild() {
const iframe = document.querySelector('iframe');
if (iframe) {
iframeReady(() => {
iframe.contentWindow.postMessage(
{
type: 'replacePath',
value: getCurrentDir(),
},
'*'
);
});
}
}
export function listenToSyncPath(router) {
window.addEventListener('message', (event) => {
if (event.data?.type !== 'replacePath') {
return;
}
const path = event.data?.value || '';
// should preserve hash for anchor
if (router.currentRoute.value.path !== path) {
router.replace(path).catch(() => {});
}
});
}

View File

@ -1,20 +1,3 @@
function iframeReady(iframe, callback) {
const doc = iframe.contentDocument || iframe.contentWindow.document;
const interval = () => {
if (iframe.contentWindow.replacePath) {
callback();
} else {
setTimeout(interval, 50);
}
};
if (doc.readyState === 'complete') {
interval();
} else {
iframe.onload = interval;
}
}
const ua = navigator.userAgent.toLowerCase();
const isMobile = /ios|iphone|ipod|ipad|android/.test(ua);
@ -25,4 +8,4 @@ export function decamelize(str, sep = '-') {
.toLowerCase();
}
export { isMobile, iframeReady };
export { isMobile };

View File

@ -25,15 +25,20 @@ export default {
},
data() {
const path = location.pathname.replace(/\/index(\.html)?/, '/');
return {
simulator: `${path}mobile.html${location.hash}`,
hasSimulator: true,
};
},
computed: {
simulator() {
if (config.site.simulator?.url) {
return config.site.simulator?.url;
}
const path = location.pathname.replace(/\/index(\.html)?/, '/');
return `${path}mobile.html${location.hash}`;
},
lang() {
const { lang } = this.$route.meta;
return lang || '';

View File

@ -214,7 +214,7 @@ export default {
position: absolute;
top: 34px;
left: 0;
width: 100px;
width: 100%;
z-index: 99;
color: #333;
line-height: 36px;

View File

@ -3,7 +3,7 @@ import { createRouter, createWebHashHistory } from 'vue-router';
import { isMobile, decamelize } from '../common';
import { config, documents } from 'site-desktop-shared';
import { getLang, setDefaultLang } from '../common/locales';
import '../common/iframe-router';
import { listenToSyncPath, syncPathToChild } from '../common/iframe-router';
if (isMobile) {
location.replace('mobile.html' + location.hash);
@ -117,7 +117,11 @@ export const router = createRouter({
});
router.afterEach(() => {
nextTick(() => window.syncPath());
nextTick(syncPathToChild);
});
if (config.site.simulator?.syncPathFromSimulator !== false) {
listenToSyncPath(router);
}
window.vueRouter = router;

View File

@ -4,7 +4,7 @@ import DemoHome from './components/DemoHome';
import { decamelize } from '../common';
import { demos, config } from 'site-mobile-shared';
import { getLang, setDefaultLang } from '../common/locales';
import '../common/iframe-router';
import { listenToSyncPath, syncPathToParent } from '../common/iframe-router';
const { locales, defaultLang } = config.site;
@ -97,8 +97,10 @@ export const router = createRouter({
watch(router.currentRoute, () => {
if (!router.currentRoute.value.redirectedFrom) {
nextTick(window.syncPath);
nextTick(syncPathToParent);
}
});
listenToSyncPath(router);
window.vueRouter = router;

View File

@ -0,0 +1,57 @@
#!/usr/bin/env node
import { command, parse, version } from 'commander';
import {
dev,
lint,
test,
clean,
build,
release,
changelog,
buildSite,
commitLint,
cliVersion,
} from '.';
version(`@vant/cli ${cliVersion}`);
command('dev').description('Run webpack dev server').action(dev);
command('lint').description('Run eslint and stylelint').action(lint);
command('test')
.description('Run unit tests through jest')
.option(
'--watch',
'Watch files for changes and rerun tests related to changed files'
)
.option(
'--clearCache',
'Clears the configured Jest cache directory and then exits'
)
.action(test);
command('clean').description('Clean all dist files').action(clean);
command('build')
.description('Compile components in production mode')
.option('--watch', 'Watch file change')
.action(build);
command('release')
.description('Compile components and release it')
.option('--tag <tag>', 'Release tag')
.action(release);
command('build-site')
.description('Compile site in production mode')
.action(buildSite);
command('changelog').description('Generate changelog').action(changelog);
command('commit-lint <gitParams>')
.description('Lint commit message')
.action(commitLint);
parse();

View File

@ -8,36 +8,77 @@ import {
} from '../common';
import { SRC_DIR, getPackageJson, getVantConfig } from '../common/constant';
type Options = {
outputPath: string;
pathResolver?: Function;
};
type PathResolver = (path: string) => string;
function genImports(components: string[], options: Options): string {
return components
function getPathByName(name: string, pathResolver?: PathResolver) {
let path = join(SRC_DIR, name);
if (pathResolver) {
path = pathResolver(path);
}
return normalizePath(path);
}
function genImports(
names: string[],
pathResolver?: PathResolver,
namedExport?: boolean
): string {
return names
.map((name) => {
let path = join(SRC_DIR, name);
if (options.pathResolver) {
path = options.pathResolver(path);
}
const pascalName = pascalize(name);
const importName = namedExport ? `{ ${pascalName} }` : pascalName;
const importPath = getPathByName(name, pathResolver);
return `import ${pascalize(name)} from '${normalizePath(path)}';`;
return `import ${importName} from '${importPath}';`;
})
.join('\n');
}
function genExports(names: string[]): string {
return names.map((name) => `${name}`).join(',\n ');
function genExports(
names: string[],
pathResolver?: PathResolver,
namedExport?: boolean
): string {
if (namedExport) {
const exports = names
.map((name) => `export * from '${getPathByName(name, pathResolver)}';`)
.join('\n');
return `
export {
install,
version,
};
${exports}
`;
}
return `
export {
install,
version,
${names.map(pascalize).join(',\n ')}
};
`;
}
export function genPackageEntry(options: Options) {
export function genPackageEntry({
outputPath,
pathResolver,
}: {
outputPath: string;
pathResolver?: PathResolver;
}) {
const names = getComponents();
const vantConfig = getVantConfig();
const namedExport = get(vantConfig, 'build.namedExport', false);
const skipInstall = get(vantConfig, 'build.skipInstall', []).map(pascalize);
const version = process.env.PACKAGE_VERSION || getPackageJson().version;
const components = names.map(pascalize);
const content = `${genImports(names, options)}
const content = `${genImports(names, pathResolver, namedExport)}
const version = '${version}';
@ -55,11 +96,7 @@ function install(app) {
});
}
export {
install,
version,
${genExports(components)}
};
${genExports(names, pathResolver, namedExport)}
export default {
install,
@ -67,5 +104,5 @@ export default {
};
`;
smartOutputFile(options.outputPath, content);
smartOutputFile(outputPath, content);
}

View File

@ -17,25 +17,25 @@ module.exports = function (api?: ConfigAPI, options: PresetOption = {}) {
return {
presets: [
[
'@babel/preset-env',
require.resolve('@babel/preset-env'),
{
modules: useESModules ? false : 'commonjs',
loose: options.loose,
},
],
'@babel/preset-typescript',
require.resolve('@babel/preset-typescript'),
require('../compiler/babel-preset-vue-ts'),
],
plugins: [
[
'@babel/plugin-transform-runtime',
require.resolve('@babel/plugin-transform-runtime'),
{
corejs: false,
useESModules,
},
],
[
'import',
require.resolve('babel-plugin-import'),
{
libraryName: 'vant',
libraryDirectory: useESModules ? 'es' : 'lib',
@ -44,7 +44,7 @@ module.exports = function (api?: ConfigAPI, options: PresetOption = {}) {
'vant',
],
[
'@vue/babel-plugin-jsx',
require.resolve('@vue/babel-plugin-jsx'),
{
enableObjectSlots: options.enableObjectSlots,
},

View File

@ -14,10 +14,10 @@ import {
} from '../common/constant';
const CSS_LOADERS = [
'style-loader',
'css-loader',
require.resolve('style-loader'),
require.resolve('css-loader'),
{
loader: 'postcss-loader',
loader: require.resolve('postcss-loader'),
options: {
postcssOptions: require(POSTCSS_CONFIG_FILE),
},
@ -25,7 +25,7 @@ const CSS_LOADERS = [
];
const VUE_LOADER = {
loader: 'vue-loader',
loader: require.resolve('vue-loader'),
options: {
compilerOptions: {
preserveWhitespace: false,
@ -88,7 +88,7 @@ export const baseConfig: WebpackConfig = {
{
test: /\.(js|ts|jsx|tsx)$/,
exclude: /node_modules\/(?!(@vant\/cli))/,
use: ['babel-loader'],
use: [require.resolve('babel-loader')],
},
{
test: /\.css$/,
@ -98,7 +98,7 @@ export const baseConfig: WebpackConfig = {
{
test: /\.less$/,
sideEffects: true,
use: [...CSS_LOADERS, 'less-loader'],
use: [...CSS_LOADERS, require.resolve('less-loader')],
},
{
test: /\.scss$/,
@ -106,7 +106,7 @@ export const baseConfig: WebpackConfig = {
use: [
...CSS_LOADERS,
{
loader: 'sass-loader',
loader: require.resolve('sass-loader'),
options: {
implementation: sass,
},
@ -115,7 +115,7 @@ export const baseConfig: WebpackConfig = {
},
{
test: /\.md$/,
use: [VUE_LOADER, '@vant/markdown-loader'],
use: [VUE_LOADER, require.resolve('@vant/markdown-loader')],
},
],
},

View File

@ -1,10 +1,5 @@
#!/usr/bin/env node
import { command, parse, version } from 'commander';
// @ts-ignore
import packageJson from '../package.json';
// commands
import { dev } from './commands/dev';
import { lint } from './commands/lint';
import { test } from './commands/jest';
@ -15,46 +10,18 @@ import { changelog } from './commands/changelog';
import { buildSite } from './commands/build-site';
import { commitLint } from './commands/commit-lint';
version(`@vant/cli ${packageJson.version}`);
export const cliVersion: string = packageJson.version;
process.env.VANT_CLI_VERSION = packageJson.version;
process.env.VANT_CLI_VERSION = cliVersion;
command('dev').description('Run webpack dev server').action(dev);
command('lint').description('Run eslint and stylelint').action(lint);
command('test')
.description('Run unit tests through jest')
.option(
'--watch',
'Watch files for changes and rerun tests related to changed files'
)
.option(
'--clearCache',
'Clears the configured Jest cache directory and then exits'
)
.action(test);
command('clean').description('Clean all dist files').action(clean);
command('build')
.description('Compile components in production mode')
.option('--watch', 'Watch file change')
.action(build);
command('release')
.description('Compile components and release it')
.option('--tag <tag>', 'Release tag')
.action(release);
command('build-site')
.description('Compile site in production mode')
.action(buildSite);
command('changelog').description('Generate changelog').action(changelog);
command('commit-lint <gitParams>')
.description('Lint commit message')
.action(commitLint);
parse();
export {
dev,
lint,
test,
clean,
build,
release,
changelog,
buildSite,
commitLint,
};

View File

@ -10,7 +10,7 @@ const messages = reactive<Messages>({
'zh-CN': defaultMessages,
});
export default {
const Locale = {
messages(): Message {
return messages[lang.value];
},
@ -24,3 +24,6 @@ export default {
deepAssign(messages, newMessages);
},
};
export default Locale;
export { Locale };

View File

@ -2,6 +2,7 @@ module.exports = {
name: 'vant',
build: {
srcDir: 'src',
namedExport: true,
skipInstall: ['lazyload'],
site: {
publicPath:
@ -15,9 +16,8 @@ module.exports = {
site: {
defaultLang: 'en-US',
versions: [
{ label: 'Vant v1', link: '/vant/v1/' },
{ label: 'Vant v2', link: '/vant/' },
{ label: 'Vant Weapp', link: '/vant-weapp/' },
{ label: 'v1', link: '/vant/v1/' },
{ label: 'v2', link: '/vant/' },
],
baiduAnalytics: {
seed: 'ad6b5732c36321f2dafed737ac2da92f',
@ -30,10 +30,14 @@ module.exports = {
locales: {
'zh-CN': {
title: 'Vant',
description: '轻量、可靠的移动端 Vue 组件库',
description: '轻量、可靠的移动端组件库',
logo: 'https://img.yzcdn.cn/vant/logo.png',
langLabel: '中',
links: [
{
logo: 'https://b.yzcdn.cn/vant/logo/weapp.svg',
url: 'https://vant-contrib.gitee.io/vant-weapp/',
},
{
logo: 'https://b.yzcdn.cn/vant/logo/github.svg',
url: 'https://github.com/youzan/vant',

View File

@ -1860,10 +1860,10 @@
resolved "https://registry.npm.taobao.org/@vant/area-data/download/@vant/area-data-1.0.0.tgz#063af9ccb5ccafa333d7dc28103937501cfec671"
integrity sha1-Bjr5zLXMr6Mz19woEDk3UBz+xnE=
"@vant/cli@^3.9.2":
version "3.9.2"
resolved "https://registry.npm.taobao.org/@vant/cli/download/@vant/cli-3.9.2.tgz#6eb7149004c8b36bc5fc08c16cc36c78bcdd3b4b"
integrity sha1-brcUkATIs2vF/AjBbMNseLzdO0s=
"@vant/cli@^3.10.0":
version "3.10.0"
resolved "https://registry.npmjs.org/@vant/cli/-/cli-3.10.0.tgz#a129adb56f15a3c31a7a2701e288ed9a642e734d"
integrity sha512-+Nj6YHxYgsgmDFrS31PiT2UwB70KO5EH3QLbzYDihoj0QfYEQmHdk+DAOeZ6IXgZR5Nb3EbZFFLKmebngYaisg==
dependencies:
"@babel/core" "^7.12.10"
"@babel/plugin-transform-runtime" "^7.12.10"