update webpack to 4.x (#425)

* update webpack to 4.x
pull/429/head
tangjinzhou 2019-01-20 21:13:55 +08:00 committed by GitHub
parent 0e78eedbfb
commit c351cba0e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 268 additions and 205 deletions

View File

@ -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'),

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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"
]
}

14
types/breadcrumb.d.ts vendored
View File

@ -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;
}

10
types/cascader.d.ts vendored
View File

@ -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'

View File

@ -6,7 +6,6 @@
import { AntdComponent } from '../component';
export default class LayoutContent extends AntdComponent {
/**
* container className
* @default undefined

View File

@ -6,7 +6,6 @@
import { AntdComponent } from '../component';
export default class LayoutFooter extends AntdComponent {
/**
* container className
* @default undefined

View File

@ -6,7 +6,6 @@
import { AntdComponent } from '../component';
export default class LayoutHeader extends AntdComponent {
/**
* container className
* @default undefined

View File

@ -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 }) {
</script>
`
: '';
newContent += style
? `
<style>
${style || ''}
</style>
`
: '';
newContent += scopedStyle
? `
<style scoped>
${scopedStyle || ''}
</style>
`
: '';
newContent += style ? `<style>${style || ''}</style>` : '';
newContent += scopedStyle ? `<style scoped>${scopedStyle || ''}</style>` : '';
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()],
};

View File

@ -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 } },
],
},
{

View File

@ -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' }),
],
});