diff --git a/antd-tools/getBabelCommonConfig.js b/antd-tools/getBabelCommonConfig.js
index 1b8c6e8fd..6f392971a 100644
--- a/antd-tools/getBabelCommonConfig.js
+++ b/antd-tools/getBabelCommonConfig.js
@@ -3,6 +3,7 @@
module.exports = function(modules) {
const plugins = [
require.resolve('babel-plugin-transform-vue-jsx'),
+ require.resolve('babel-plugin-inline-import-data-uri'),
require.resolve('babel-plugin-transform-es3-member-expression-literals'),
require.resolve('babel-plugin-transform-es3-property-literals'),
require.resolve('babel-plugin-transform-object-assign'),
diff --git a/antd-tools/getWebpackConfig.js b/antd-tools/getWebpackConfig.js
index e8bb243b1..6b92bf4ee 100644
--- a/antd-tools/getWebpackConfig.js
+++ b/antd-tools/getWebpackConfig.js
@@ -1,28 +1,43 @@
const path = require('path');
const webpack = require('webpack');
-const ExtractTextPlugin = require('extract-text-webpack-plugin');
+const WebpackBar = require('webpackbar');
+const webpackMerge = require('webpack-merge');
+const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
-const deepAssign = require('deep-assign');
-const chalk = require('chalk');
const postcssConfig = require('./postcssConfig');
+const CleanUpStatsPlugin = require('./utils/CleanUpStatsPlugin');
+
const distFileBaseName = 'antd';
-module.exports = function(modules) {
+
+const svgRegex = /\.svg(\?v=\d+\.\d+\.\d+)?$/;
+const svgOptions = {
+ limit: 10000,
+ minetype: 'image/svg+xml',
+};
+
+const imageOptions = {
+ limit: 10000,
+};
+
+function getWebpackConfig(modules) {
const pkg = require(path.join(process.cwd(), 'package.json'));
const babelConfig = require('./getBabelCommonConfig')(modules || false);
const pluginImportOptions = [
{
style: true,
- libraryName: 'antd',
+ libraryName: distFileBaseName,
libraryDirectory: 'components',
},
];
-
- // if (distFileBaseName !== 'antd') { pluginImportOptions.push({ style:
- // 'css', libraryDirectory: 'components', libraryName: 'antd', }) }
-
babelConfig.plugins.push([require.resolve('babel-plugin-import'), pluginImportOptions]);
+ if (modules === false) {
+ babelConfig.plugins.push(require.resolve('./replaceLib'));
+ }
+
const config = {
devtool: 'source-map',
@@ -86,74 +101,75 @@ module.exports = function(modules) {
},
{
test: /\.css$/,
- use: ExtractTextPlugin.extract({
- use: [
- {
- loader: 'css-loader',
- options: {
- sourceMap: true,
- },
+ use: [
+ MiniCssExtractPlugin.loader,
+ {
+ loader: 'css-loader',
+ options: {
+ sourceMap: true,
},
- {
- loader: 'postcss-loader',
- options: Object.assign({}, postcssConfig, { sourceMap: true }),
- },
- ],
- }),
+ },
+ {
+ loader: 'postcss-loader',
+ options: Object.assign({}, postcssConfig, { sourceMap: true }),
+ },
+ ],
},
{
test: /\.less$/,
- use: ExtractTextPlugin.extract({
- use: [
- {
- loader: 'css-loader',
- options: {
- sourceMap: true,
- },
+ use: [
+ MiniCssExtractPlugin.loader,
+ {
+ loader: 'css-loader',
+ options: {
+ sourceMap: true,
},
- {
- loader: 'postcss-loader',
- options: Object.assign({}, postcssConfig, { sourceMap: true }),
+ },
+ {
+ loader: 'postcss-loader',
+ options: Object.assign({}, postcssConfig, { sourceMap: true }),
+ },
+ {
+ loader: 'less-loader',
+ options: {
+ sourceMap: true,
+ javascriptEnabled: true,
},
- {
- loader: 'less-loader',
- options: {
- sourceMap: true,
- },
- },
- ],
- }),
+ },
+ ],
+ },
+ // Images
+ {
+ test: svgRegex,
+ loader: 'url-loader',
+ options: svgOptions,
+ },
+ {
+ test: /\.(png|jpg|jpeg|gif)(\?v=\d+\.\d+\.\d+)?$/i,
+ loader: 'url-loader',
+ options: imageOptions,
},
],
},
plugins: [
- new ExtractTextPlugin({ filename: '[name].css', disable: false, allChunks: true }),
new CaseSensitivePathsPlugin(),
new webpack.BannerPlugin(`
-${distFileBaseName} v${pkg.version}
+${pkg.name} v${pkg.version}
Copyright 2017-present, ant-design-vue.
All rights reserved.
`),
- new webpack.ProgressPlugin((percentage, msg, addInfo) => {
- const stream = process.stderr;
- if (stream.isTTY && percentage < 0.71) {
- stream.cursorTo(0);
- stream.write(`📦 ${chalk.magenta(msg)} (${chalk.magenta(addInfo)})`);
- stream.clearLine(1);
- } else if (percentage === 1) {
- console.log(chalk.green('\nwebpack: bundle build is now finished.'));
- }
+ new WebpackBar({
+ name: '🚚 Ant Design Vue Tools',
+ color: '#2f54eb',
}),
+ new CleanUpStatsPlugin(),
],
};
if (process.env.RUN_ENV === 'PRODUCTION') {
const entry = ['./index'];
- config.entry = {
- [`${distFileBaseName}.min`]: entry,
- };
config.externals = {
vue: {
root: 'Vue',
@@ -164,38 +180,61 @@ All rights reserved.
};
config.output.library = distFileBaseName;
config.output.libraryTarget = 'umd';
-
- const uncompressedConfig = deepAssign({}, config);
-
- config.plugins = config.plugins.concat([
- new webpack.optimize.UglifyJsPlugin({
- sourceMap: true,
- output: {
- ascii_only: true,
- },
- compress: {
- warnings: false,
- },
- }),
- new webpack.optimize.ModuleConcatenationPlugin(),
- new webpack.LoaderOptionsPlugin({ minimize: true }),
- new webpack.DefinePlugin({
- 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production'),
- }),
- ]);
-
- uncompressedConfig.entry = {
- [distFileBaseName]: entry,
+ config.optimization = {
+ minimizer: [
+ new UglifyJsPlugin({
+ cache: true,
+ parallel: true,
+ sourceMap: true,
+ uglifyOptions: {
+ warnings: false,
+ },
+ }),
+ ],
};
- uncompressedConfig.plugins.push(
- new webpack.DefinePlugin({
- 'process.env.NODE_ENV': JSON.stringify('development'),
- }),
- );
+ // Development
+ const uncompressedConfig = webpackMerge({}, config, {
+ entry: {
+ [distFileBaseName]: entry,
+ },
+ mode: 'development',
+ plugins: [
+ new MiniCssExtractPlugin({
+ filename: '[name].css',
+ }),
+ ],
+ });
- return [config, uncompressedConfig];
+ // Production
+ const prodConfig = webpackMerge({}, config, {
+ entry: {
+ [`${distFileBaseName}.min`]: entry,
+ },
+ mode: 'production',
+ plugins: [
+ new webpack.optimize.ModuleConcatenationPlugin(),
+ new webpack.LoaderOptionsPlugin({
+ minimize: true,
+ }),
+ new MiniCssExtractPlugin({
+ filename: '[name].css',
+ }),
+ ],
+ optimization: {
+ minimizer: [new OptimizeCSSAssetsPlugin({})],
+ },
+ });
+
+ return [prodConfig, uncompressedConfig];
}
return config;
-};
+}
+
+getWebpackConfig.webpack = webpack;
+getWebpackConfig.svgRegex = svgRegex;
+getWebpackConfig.svgOptions = svgOptions;
+getWebpackConfig.imageOptions = imageOptions;
+
+module.exports = getWebpackConfig;
diff --git a/antd-tools/transformLess.js b/antd-tools/transformLess.js
index 2a03eefe2..269795e90 100644
--- a/antd-tools/transformLess.js
+++ b/antd-tools/transformLess.js
@@ -17,6 +17,7 @@ function transformLess(lessFile, config = {}) {
paths: [path.dirname(resolvedLessFile)],
filename: resolvedLessFile,
plugins: [new NpmImportPlugin({ prefix: '~' })],
+ javascriptEnabled: true,
};
return less
.render(data, lessOpts)
diff --git a/antd-tools/utils/CleanUpStatsPlugin.js b/antd-tools/utils/CleanUpStatsPlugin.js
new file mode 100644
index 000000000..300168c4f
--- /dev/null
+++ b/antd-tools/utils/CleanUpStatsPlugin.js
@@ -0,0 +1,38 @@
+// We should use `stats` props of webpack. But it not work in v4.
+class CleanUpStatsPlugin {
+ constructor(option) {
+ this.option = {
+ MiniCSSExtractPlugin: true,
+ tsLoader: true,
+ ...option,
+ };
+ }
+
+ shouldPickStatChild(child) {
+ const { MiniCSSExtractPlugin } = this.option;
+ if (MiniCSSExtractPlugin && child.name.includes('mini-css-extract-plugin')) return false;
+ return true;
+ }
+
+ shouldPickWarning(message) {
+ const { tsLoader } = this.option;
+ if (tsLoader && /export .* was not found in .*/.test(message)) {
+ return false;
+ }
+ return true;
+ }
+
+ apply(compiler) {
+ compiler.hooks.done.tap('CleanUpStatsPlugin', stats => {
+ const { children, warnings } = stats.compilation;
+ if (Array.isArray(children)) {
+ stats.compilation.children = children.filter(child => this.shouldPickStatChild(child));
+ }
+ if (Array.isArray(warnings)) {
+ stats.compilation.warnings = warnings.filter(message => this.shouldPickWarning(message));
+ }
+ });
+ }
+}
+
+module.exports = CleanUpStatsPlugin;
diff --git a/package.json b/package.json
index 2e5c69ae7..591b8706b 100644
--- a/package.json
+++ b/package.json
@@ -26,6 +26,7 @@
"scripts": {
"dev": "cross-env NODE_ENV=development ENTRY_INDEX=dev ./node_modules/.bin/webpack-dev-server --open --hot --port 3001",
"start": "cross-env NODE_ENV=development ./node_modules/.bin/webpack-dev-server --open --hot",
+ "site-test": "cross-env NODE_ENV=production webpack --config ./webpack.site.config.js",
"test": "cross-env NODE_ENV=test jest --config .jest.js",
"site": "node scripts/run.js site-dist",
"copy": "node scripts/run.js copy-html",
@@ -51,8 +52,8 @@
},
"homepage": "https://github.com/vueComponent/ant-design-vue",
"pre-commit": [
- "lint:style",
- "lint"
+ "lint",
+ "prettier"
],
"peerDependencies": {
"vue": ">=2.5.0",
@@ -68,12 +69,13 @@
"axios": "^0.18.0",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
- "babel-eslint": "^8.0.1",
+ "babel-eslint": "^10.0.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-jest": "^22.4.3",
"babel-loader": "^7.1.2",
"babel-plugin-add-module-exports": "^1.0.0",
"babel-plugin-import": "^1.1.1",
+ "babel-plugin-inline-import-data-uri": "^1.0.1",
"babel-plugin-istanbul": "^4.1.1",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-syntax-jsx": "^6.18.0",
@@ -112,26 +114,28 @@
"gulp-babel": "^7.0.0",
"gulp-strip-code": "^0.1.4",
"highlight.js": "^9.12.0",
- "html-webpack-plugin": "^2.30.1",
+ "html-webpack-plugin": "^3.2.0",
"husky": "^0.14.3",
"istanbul-instrumenter-loader": "^3.0.0",
"jest": "^22.4.3",
"jest-serializer-vue": "^1.0.0",
"js-base64": "^2.4.8",
"jsonp": "^0.2.1",
- "less": "^2.7.2",
- "less-loader": "^4.0.5",
+ "less": "^3.9.0",
+ "less-loader": "^4.1.0",
"less-plugin-npm-import": "^2.1.0",
"markdown-it": "^8.4.0",
"markdown-it-anchor": "^4.0.0",
"marked": "^0.3.7",
"merge2": "^1.2.1",
+ "mini-css-extract-plugin": "^0.5.0",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"mockdate": "^2.0.2",
"nprogress": "^0.2.0",
- "postcss": "^6.0.20",
- "postcss-loader": "^2.1.2",
+ "optimize-css-assets-webpack-plugin": "^5.0.1",
+ "postcss": "^7.0.6",
+ "postcss-loader": "^3.0.0",
"pre-commit": "^1.2.2",
"prettier": "^1.15.3",
"querystring": "^0.2.0",
@@ -146,21 +150,24 @@
"stylelint-config-prettier": "^4.0.0",
"stylelint-config-standard": "^18.2.0",
"through2": "^2.0.3",
+ "uglifyjs-webpack-plugin": "^2.1.1",
+ "url-loader": "^1.1.2",
"vue": "^2.5.16",
- "vue-antd-md-loader": "^1.0.3",
+ "vue-antd-md-loader": "^1.1.0",
"vue-clipboard2": "0.0.8",
"vue-i18n": "^8.3.2",
"vue-infinite-scroll": "^2.0.2",
"vue-jest": "^2.5.0",
- "vue-loader": "^13.0.5",
+ "vue-loader": "^15.5.1",
"vue-router": "^3.0.1",
"vue-server-renderer": "^2.5.16",
"vue-template-compiler": "^2.5.16",
"vue-virtual-scroller": "^0.12.0",
- "webpack": "^3.11.0",
- "webpack-chunk-hash": "^0.5.0",
- "webpack-dev-server": "^2.8.2",
- "webpack-merge": "^4.1.1"
+ "webpack": "^4.28.4",
+ "webpack-cli": "^3.2.1",
+ "webpack-dev-server": "^3.1.14",
+ "webpack-merge": "^4.1.1",
+ "webpackbar": "^3.1.5"
},
"dependencies": {
"@ant-design/icons": "^1.1.15",
@@ -190,5 +197,11 @@
"shallowequal": "^1.0.2",
"vue-ref": "^1.0.4",
"warning": "^3.0.0"
- }
+ },
+ "sideEffects": [
+ "dist/*",
+ "es/**/style/*",
+ "lib/**/style/*",
+ "*.less"
+ ]
}
diff --git a/types/breadcrumb.d.ts b/types/breadcrumb.d.ts
index abdeafad2..f8f9c6bcb 100644
--- a/types/breadcrumb.d.ts
+++ b/types/breadcrumb.d.ts
@@ -34,7 +34,15 @@ export declare class Breadcrumb extends AntdComponent {
* Custom item renderer, slot="itemRender" and slot-scope="{route, params, routes, paths}"
* @type Function
*/
- itemRender: (
- { route, params, routes, paths }: { route: any; params: any; routes: any; paths: any },
- ) => VNode;
+ itemRender: ({
+ route,
+ params,
+ routes,
+ paths,
+ }: {
+ route: any;
+ params: any;
+ routes: any;
+ paths: any;
+ }) => VNode;
}
diff --git a/types/cascader.d.ts b/types/cascader.d.ts
index 800262c71..ec2fb742f 100644
--- a/types/cascader.d.ts
+++ b/types/cascader.d.ts
@@ -86,9 +86,13 @@ export declare class Cascader extends AntdComponent {
* @default labels => labels.join(' / ')
* @type Function
*/
- displayRender: (
- { labels, selectedOptions }: { labels: string[]; selectedOptions: CascaderOptionType[] },
- ) => VNode;
+ displayRender: ({
+ labels,
+ selectedOptions,
+ }: {
+ labels: string[];
+ selectedOptions: CascaderOptionType[];
+ }) => VNode;
/**
* expand current item when click or hover, one of 'click' 'hover'
diff --git a/types/layout/layout-content.d.ts b/types/layout/layout-content.d.ts
index 54948f7b4..419c2193b 100644
--- a/types/layout/layout-content.d.ts
+++ b/types/layout/layout-content.d.ts
@@ -6,7 +6,6 @@
import { AntdComponent } from '../component';
export default class LayoutContent extends AntdComponent {
-
/**
* container className
* @default undefined
diff --git a/types/layout/layout-footer.d.ts b/types/layout/layout-footer.d.ts
index d8f155d05..c40a6e7f3 100644
--- a/types/layout/layout-footer.d.ts
+++ b/types/layout/layout-footer.d.ts
@@ -6,7 +6,6 @@
import { AntdComponent } from '../component';
export default class LayoutFooter extends AntdComponent {
-
/**
* container className
* @default undefined
diff --git a/types/layout/layout-header.d.ts b/types/layout/layout-header.d.ts
index c8a56cff6..3a9b73399 100644
--- a/types/layout/layout-header.d.ts
+++ b/types/layout/layout-header.d.ts
@@ -6,7 +6,6 @@
import { AntdComponent } from '../component';
export default class LayoutHeader extends AntdComponent {
-
/**
* container className
* @default undefined
diff --git a/webpack.base.config.js b/webpack.base.config.js
index 25342876a..0ef3eb21f 100644
--- a/webpack.base.config.js
+++ b/webpack.base.config.js
@@ -2,6 +2,8 @@ const path = require('path');
const hljs = require('highlight.js');
const Token = require('markdown-it/lib/token');
const cheerio = require('cheerio');
+const WebpackBar = require('webpackbar');
+const VueLoaderPlugin = require('vue-loader/lib/plugin');
const getBabelCommonConfig = require('./antd-tools/getBabelCommonConfig');
const babelConfig = getBabelCommonConfig(false);
@@ -129,52 +131,45 @@ md.core.ruler.push('update_template', function replace({ tokens }) {
`
: '';
- newContent += style
- ? `
-
- `
- : '';
- newContent += scopedStyle
- ? `
-
- `
- : '';
+ newContent += style ? `` : '';
+ newContent += scopedStyle ? `` : '';
const t = new Token('html_block', '', 0);
t.content = newContent;
tokens.push(t);
}
});
-
+const vueLoaderOptions = {
+ loaders: {
+ js: [
+ {
+ loader: 'babel-loader',
+ options: {
+ presets: ['env'],
+ plugins: ['transform-vue-jsx', 'transform-object-rest-spread'],
+ },
+ },
+ ],
+ },
+};
module.exports = {
+ mode: 'production',
entry: {
index: [`./site/${process.env.ENTRY_INDEX || 'index'}.js`],
},
module: {
rules: [
{
- test: /\.md/,
+ test: /\.md$/,
use: [
+ {
+ loader: 'vue-loader',
+ options: vueLoaderOptions,
+ },
{
loader: 'vue-antd-md-loader',
options: Object.assign(md, {
wrapper: 'div',
- vueLoaderOptions: {
- loaders: {
- js: [
- {
- loader: 'babel-loader',
- options: {
- presets: ['env'],
- plugins: ['transform-vue-jsx', 'transform-object-rest-spread'],
- },
- },
- ],
- },
- },
+ raw: true,
}),
},
],
@@ -182,23 +177,7 @@ module.exports = {
{
test: /\.vue$/,
loader: 'vue-loader',
- options: {
- loaders: {
- js: [
- {
- loader: 'babel-loader',
- options: {
- presets: ['env'],
- plugins: [
- 'transform-vue-jsx',
- 'transform-object-rest-spread',
- 'syntax-dynamic-import',
- ],
- },
- },
- ],
- },
- },
+ options: vueLoaderOptions,
},
{
test: /\.(js|jsx)$/,
@@ -225,4 +204,5 @@ module.exports = {
'@': path.join(__dirname, ''),
},
},
+ plugins: [new VueLoaderPlugin(), new WebpackBar()],
};
diff --git a/webpack.config.js b/webpack.config.js
index ece2fa47e..fa75971f9 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -5,6 +5,7 @@ const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.config');
module.exports = merge(baseWebpackConfig, {
+ mode: 'development',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/ant-design-vue/',
@@ -20,7 +21,7 @@ module.exports = merge(baseWebpackConfig, {
loader: 'css-loader',
options: { sourceMap: true },
},
- { loader: 'less-loader', options: { sourceMap: true } },
+ { loader: 'less-loader', options: { sourceMap: true, javascriptEnabled: true } },
],
},
{
diff --git a/webpack.site.config.js b/webpack.site.config.js
index 0c80c9b0d..ca6d7f820 100644
--- a/webpack.site.config.js
+++ b/webpack.site.config.js
@@ -1,86 +1,67 @@
const path = require('path');
const webpack = require('webpack');
-const ExtractTextPlugin = require('extract-text-webpack-plugin');
-const WebpackChunkHash = require('webpack-chunk-hash');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.config');
-const modulePlugin = new ExtractTextPlugin({
- filename: '[name].[chunkhash].css',
- allChunks: true,
-});
-
module.exports = merge(baseWebpackConfig, {
output: {
path: path.resolve(__dirname, './site-dist'),
publicPath: '/ant-design-vue/',
- filename: '[name].[chunkhash].js',
- chunkFilename: '[chunkhash].async.js',
+ filename: '[name].[contenthash:8].js',
+ chunkFilename: '[contenthash:8].async.js',
},
module: {
rules: [
{
test: /\.less$/,
- use: modulePlugin.extract({
- fallback: 'style-loader',
- use: [
- {
- loader: 'css-loader',
- },
- {
- loader: 'postcss-loader',
- },
- { loader: 'less-loader' },
- ],
- }),
+ use: [
+ MiniCssExtractPlugin.loader,
+ 'css-loader',
+ 'postcss-loader',
+ { loader: 'less-loader', options: { javascriptEnabled: true } },
+ ],
},
{
test: /\.css$/,
- use: modulePlugin.extract({
- fallback: 'style-loader',
- use: [
- {
- loader: 'css-loader',
- },
- {
- loader: 'postcss-loader',
- },
- ],
- }),
+ use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'],
},
],
},
+ optimization: {
+ splitChunks: {
+ cacheGroups: {
+ vendors: {
+ name: `chunk-vendors`,
+ test: /[\\/]node_modules[\\/]/,
+ priority: -10,
+ chunks: 'initial',
+ },
+ common: {
+ name: `chunk-common`,
+ minChunks: 2,
+ priority: -20,
+ chunks: 'initial',
+ reuseExistingChunk: true,
+ },
+ },
+ },
+ },
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"',
},
}),
- new webpack.optimize.CommonsChunkPlugin({
- name: 'vender',
- minChunks: function(module) {
- return /node_modules/.test(module.context);
- },
- }),
- new webpack.optimize.CommonsChunkPlugin({
- name: 'manifest',
- minChunks: Infinity,
- }),
- new webpack.optimize.UglifyJsPlugin({
- compress: {
- warnings: false,
- },
- }),
new HtmlWebpackPlugin({
template: './site/index.html',
inject: true,
production: true,
}),
- new webpack.LoaderOptionsPlugin({
- minimize: true,
+ new MiniCssExtractPlugin({
+ filename: '[name].[contenthash:8].css',
+ chunkFilename: '[id].[contenthash:8].css',
}),
- modulePlugin,
- new WebpackChunkHash({ algorithm: 'md5' }),
],
});