diff --git a/packages/vant-cli/package.json b/packages/vant-cli/package.json index 8ac9eea49..5068f19b0 100644 --- a/packages/vant-cli/package.json +++ b/packages/vant-cli/package.json @@ -52,6 +52,7 @@ "@babel/plugin-transform-runtime": "^7.6.2", "@babel/preset-env": "^7.7.1", "@babel/preset-typescript": "^7.7.2", + "@nuxt/friendly-errors-webpack-plugin": "^2.5.0", "@types/jest": "^24.0.22", "@vant/eslint-config": "^1.4.0", "@vant/markdown-loader": "^2.2.0", diff --git a/packages/vant-cli/src/commands/build.ts b/packages/vant-cli/src/commands/build.ts index c75f17d80..f278e95bb 100644 --- a/packages/vant-cli/src/commands/build.ts +++ b/packages/vant-cli/src/commands/build.ts @@ -1,9 +1,13 @@ +import webpack from 'webpack'; +import { start, error, success } from 'signale'; +import { packageConfig } from '../config/webpack.package'; import { join } from 'path'; -import { remove, copy, readdirSync } from 'fs-extra'; import { clean } from './clean'; +import { remove, copy, readdirSync } from 'fs-extra'; import { compileJs } from '../compiler/compile-js'; import { compileSfc } from '../compiler/compile-sfc'; import { compileStyle } from '../compiler/compile-style'; +import { genPackageEntry } from '../compiler/gen-package-entry'; import { SRC_DIR, LIB_DIR, ES_DIR } from '../common/constant'; import { isDir, @@ -40,15 +44,49 @@ function setModuleEnv(value: string) { process.env.BABEL_MODULE = value; } +function buildPackage(isMinify: boolean) { + return new Promise((resolve, reject) => { + webpack(packageConfig(isMinify), (err, stats) => { + if (err || stats.hasErrors()) { + reject(); + } else { + resolve(); + } + }); + }); +} + export async function build() { clean(); await copy(SRC_DIR, ES_DIR); await copy(SRC_DIR, LIB_DIR); - setModuleEnv('esmodule'); - await compileDir(ES_DIR); + start('Build esmodule outputs'); + try { + setModuleEnv('esmodule'); + await compileDir(ES_DIR); + success('Build esmodule outputs'); + } catch (err) { + error('Build esmodule outputs'); + } - setModuleEnv('commonjs'); - await compileDir(LIB_DIR); + start('Build commonjs outputs'); + try { + setModuleEnv('commonjs'); + await compileDir(LIB_DIR); + success('Build commonjs outputs'); + } catch (err) { + error('Build commonjs outputs'); + } + + start('Build packed outputs'); + try { + genPackageEntry(); + await buildPackage(false); + await buildPackage(true); + success('Build packed outputs'); + } catch (err) { + error('Build packed outputs'); + } } diff --git a/packages/vant-cli/src/commands/dev.ts b/packages/vant-cli/src/commands/dev.ts index a5811c781..24252037e 100644 --- a/packages/vant-cli/src/commands/dev.ts +++ b/packages/vant-cli/src/commands/dev.ts @@ -1,15 +1,15 @@ import webpack from 'webpack'; import WebpackDevServer from 'webpack-dev-server'; -import webpackDevConfig from '../config/webpack.site.dev'; import { getPort } from 'portfinder'; import { clean } from '../commands/clean'; +import { siteDevConfig } from '../config/webpack.site.dev'; import { genMobileConfig } from '../compiler/gen-mobile-config'; import { genDesktopConfig } from '../compiler/gen-desktop-config'; function runWebpack() { const server = new WebpackDevServer( - webpack(webpackDevConfig), - (webpackDevConfig as any).devServer + webpack(siteDevConfig), + (siteDevConfig as any).devServer ); getPort( diff --git a/packages/vant-cli/src/common/constant.ts b/packages/vant-cli/src/common/constant.ts index b405f2ad9..bd6b648c1 100644 --- a/packages/vant-cli/src/common/constant.ts +++ b/packages/vant-cli/src/common/constant.ts @@ -6,8 +6,10 @@ export const LIB_DIR = join(CWD, 'lib'); export const SRC_DIR = join(CWD, 'src'); export const DOCS_DIR = join(CWD, 'docs'); export const CONFIG_FILE = join(CWD, 'components.config.js'); +export const PACKAGE_JSON_FILE = join(CWD, 'package.json'); export const DIST_DIR = join(__dirname, '../../dist'); export const CONFIG_DIR = join(__dirname, '../config'); +export const PACKAGE_ENTRY_FILE = join(DIST_DIR, 'index.js'); export const MOBILE_CONFIG_FILE = join(DIST_DIR, 'mobile-config.js'); export const DESKTOP_CONFIG_FILE = join(DIST_DIR, 'desktop-config.js'); export const BABEL_CONFIG_FILE = join(CONFIG_DIR, 'babel.config.js'); diff --git a/packages/vant-cli/src/compiler/gen-package-entry.ts b/packages/vant-cli/src/compiler/gen-package-entry.ts new file mode 100644 index 000000000..b66b0401b --- /dev/null +++ b/packages/vant-cli/src/compiler/gen-package-entry.ts @@ -0,0 +1,66 @@ +import { join, relative } from 'path'; +import { writeFileSync } from 'fs-extra'; +import { pascalize, getComponents } from '../common'; +import { + SRC_DIR, + DIST_DIR, + PACKAGE_JSON_FILE, + PACKAGE_ENTRY_FILE +} from '../common/constant'; + +// eslint-disable-next-line +const packageJson = require(PACKAGE_JSON_FILE); +const version = process.env.PACKAGE_VERSION || packageJson.version; + +function genImports(components: string[]): string { + return components + .map(name => { + const relativePath = relative(DIST_DIR, join(SRC_DIR, name)); + return `import ${pascalize(name)} from '${relativePath}';`; + }) + .join('\n'); +} + +function genExports(names: string[]): string { + return names.map(name => `${name}`).join(',\n '); +} + +export function genPackageEntry() { + const components = getComponents(); + const names = components.map(item => pascalize(item)); + + const content = `${genImports(components)} + +const version = '${version}'; +const components = [ + ${names.join(',\n ')} +]; + +function install() { + components.forEach(item => { + if (item.install) { + Vue.use(Component); + } else if (item.name) { + Vue.component(item.name, item); + } + }); +}; + +if (typeof window !== 'undefined' && window.Vue) { + install(window.Vue); +} + +export { + install, + version, + ${genExports(names)} +}; + +export default { + install, + version +}; +`; + + writeFileSync(PACKAGE_ENTRY_FILE, content); +} diff --git a/packages/vant-cli/src/config/webpack.base.ts b/packages/vant-cli/src/config/webpack.base.ts index 4274bfd3c..3d33fd51c 100644 --- a/packages/vant-cli/src/config/webpack.base.ts +++ b/packages/vant-cli/src/config/webpack.base.ts @@ -1,5 +1,6 @@ - import sass from 'sass'; +// @ts-ignore +import FriendlyErrorsPlugin from '@nuxt/friendly-errors-webpack-plugin'; import { VueLoaderPlugin } from 'vue-loader'; import { POSTCSS_CONFIG_FILE } from '../common/constant'; @@ -16,7 +17,7 @@ const CSS_LOADERS = [ } ]; -module.exports = { +export const baseConfig = { mode: 'development', resolve: { extensions: ['.js', '.ts', '.tsx', '.jsx', '.vue', '.less'] @@ -72,7 +73,11 @@ module.exports = { } ] }, - plugins: [new VueLoaderPlugin()] + plugins: [ + new VueLoaderPlugin(), + new FriendlyErrorsPlugin({ + clearConsole: false, + logLevel: 'WARNING' + }) + ] }; - -export default module.exports; diff --git a/packages/vant-cli/src/config/webpack.package.ts b/packages/vant-cli/src/config/webpack.package.ts new file mode 100644 index 000000000..4a16e3c49 --- /dev/null +++ b/packages/vant-cli/src/config/webpack.package.ts @@ -0,0 +1,39 @@ +import { join } from 'path'; +import merge from 'webpack-merge'; +import { baseConfig } from './webpack.base'; +import { LIB_DIR, DIST_DIR, CONFIG_FILE } from '../common/constant'; + +// eslint-disable-next-line +const config = require(CONFIG_FILE); +const { name } = config; + +export function packageConfig(isMinify: boolean) { + return merge(baseConfig as any, { + mode: 'production', + entry: { + [name]: join(DIST_DIR, 'index.js') + }, + stats: 'none', + output: { + path: LIB_DIR, + library: name, + libraryTarget: 'umd', + filename: isMinify ? '[name].min.js' : '[name].js', + umdNamedDefine: true, + // https://github.com/webpack/webpack/issues/6522 + globalObject: "typeof self !== 'undefined' ? self : this" + }, + externals: { + vue: { + root: 'Vue', + commonjs: 'vue', + commonjs2: 'vue', + amd: 'vue' + } + }, + performance: false, + optimization: { + minimize: isMinify + } + }); +} diff --git a/packages/vant-cli/src/config/webpack.site.dev.ts b/packages/vant-cli/src/config/webpack.site.dev.ts index 3cc049f33..57a0e9f3b 100644 --- a/packages/vant-cli/src/config/webpack.site.dev.ts +++ b/packages/vant-cli/src/config/webpack.site.dev.ts @@ -1,14 +1,14 @@ -import { join } from 'path'; import merge from 'webpack-merge'; -import baseConfig from './webpack.base'; import HtmlWebpackPlugin from 'html-webpack-plugin'; +import { join } from 'path'; +import { baseConfig } from './webpack.base'; import { CONFIG_FILE } from '../common/constant'; // eslint-disable-next-line const config = require(CONFIG_FILE); const title = `${config.title} - ${config.description}`; -module.exports = merge(baseConfig, { +export const siteDevConfig = merge(baseConfig as any, { entry: { 'site-desktop': join(__dirname, '../../site/desktop/main.js'), 'site-mobile': join(__dirname, '../../site/mobile/main.js') @@ -53,5 +53,3 @@ module.exports = merge(baseConfig, { }) ] }); - -export default module.exports; diff --git a/packages/vant-cli/src/config/webpack.site.prd.ts b/packages/vant-cli/src/config/webpack.site.prd.ts index b73931ff2..55d3aeeca 100644 --- a/packages/vant-cli/src/config/webpack.site.prd.ts +++ b/packages/vant-cli/src/config/webpack.site.prd.ts @@ -1,8 +1,8 @@ import { join } from 'path'; import merge from 'webpack-merge'; -import config from './webpack.site.dev'; +import { siteDevConfig } from './webpack.site.dev'; -module.exports = merge(config, { +export const sitePrdConfig = merge(siteDevConfig, { mode: 'production', output: { path: join(__dirname, '../../site/dist'), @@ -11,5 +11,3 @@ module.exports = merge(config, { chunkFilename: 'async_[name].[chunkhash:8].js' } }); - -export default module.exports; diff --git a/packages/vant-cli/yarn.lock b/packages/vant-cli/yarn.lock index 6dfecb292..24ce2d141 100644 --- a/packages/vant-cli/yarn.lock +++ b/packages/vant-cli/yarn.lock @@ -935,6 +935,16 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" +"@nuxt/friendly-errors-webpack-plugin@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@nuxt/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-2.5.0.tgz#5374665bc72d34b7dbadcc361a4777e3f0f5d46b" + integrity sha512-pUgPFmRL56/xuTCGN5rqgTfxvs1N/AYJw7q7tUHiZaBm3UyPgbIVPkadS9njwbFbPD2XcebVy7npQMMVwQJWfA== + dependencies: + chalk "^2.3.2" + consola "^2.6.0" + error-stack-parser "^2.0.0" + string-width "^2.0.0" + "@octokit/endpoint@^5.5.0": version "5.5.1" resolved "https://registry.npm.taobao.org/@octokit/endpoint/download/@octokit/endpoint-5.5.1.tgz?cache=0&sync_timestamp=1572751977515&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40octokit%2Fendpoint%2Fdownload%2F%40octokit%2Fendpoint-5.5.1.tgz#2eea81e110ca754ff2de11c79154ccab4ae16b3f" @@ -2988,6 +2998,11 @@ connect-history-api-fallback@^1.6.0: resolved "https://registry.npm.taobao.org/connect-history-api-fallback/download/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" integrity sha1-izIIk1kwjRERFdgcrT/Oq4iPl7w= +consola@^2.6.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/consola/-/consola-2.11.0.tgz#9bb35d850d8cecde894ce2eb4d792fa6b90d9013" + integrity sha512-2bcAqHastlPSCvZ+ur8bgHInGAWvUnysWz3h3xRX+/XZoCY7avolJJnVXOPGoVoyCcg1b231XixonoArmgxaoA== + console-browserify@^1.1.0: version "1.2.0" resolved "https://registry.npm.taobao.org/console-browserify/download/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" @@ -3877,6 +3892,13 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +error-stack-parser@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.4.tgz#a757397dc5d9de973ac9a5d7d4e8ade7cfae9101" + integrity sha512-fZ0KkoxSjLFmhW5lHbUT3tLwy3nX1qEzMYo8koY1vrsAco53CMT1djnBSeC/wUjTEZRhZl9iRw7PaMaxfJ4wzQ== + dependencies: + stackframe "^1.1.0" + es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: version "1.16.0" resolved "https://registry.npm.taobao.org/es-abstract/download/es-abstract-1.16.0.tgz?cache=0&sync_timestamp=1571460404163&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fes-abstract%2Fdownload%2Fes-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" @@ -9684,6 +9706,11 @@ stack-utils@^1.0.1: resolved "https://registry.npm.taobao.org/stack-utils/download/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" integrity sha1-M+ujiXeIVYvr/C2wWdwVjsNs67g= +stackframe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.1.0.tgz#e3fc2eb912259479c9822f7d1f1ff365bd5cbc83" + integrity sha512-Vx6W1Yvy+AM1R/ckVwcHQHV147pTPBKWCRLrXMuPrFVfvBUc3os7PR1QLIWCMhPpRg5eX9ojzbQIMLGBwyLjqg== + state-toggle@^1.0.0: version "1.0.2" resolved "https://registry.npm.taobao.org/state-toggle/download/state-toggle-1.0.2.tgz#75e93a61944116b4959d665c8db2d243631d6ddc"