UNPKG

@ctsj/build

Version:

一个基于webpack的打包工具

284 lines (277 loc) 7.86 kB
const path = require('path'); const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); const UselessFilesCleanWebpackPlugin = require('useless-files-clean-webpack-plugin'); const CompressionPlugin = require('compression-webpack-plugin'); const WebpackBar = require('webpackbar'); const commandArgs = require('../commandArgs'); const Util = require('../util'); const { getPostCssConfigPath, isDev, isProd } = require('../util'); const argIndex = isDev() ? 8 : 6; const runtimePath = commandArgs.toCommandArgs(process.argv[argIndex]).get('runtimepath'); const APP_PATH = path.resolve(runtimePath, 'src'); // 项目src目录 const devLoaders = isDev() ? [] : ['thread-loader']; const babelConfig = { presets: [ [ '@babel/preset-env', // { // useBuiltIns: 'usage', // corejs: { version: 3, proposals: true }, // }, ], '@babel/preset-react', ], plugins: [ '@babel/plugin-transform-runtime', '@babel/plugin-syntax-dynamic-import', '@babel/plugin-proposal-function-bind', '@babel/plugin-proposal-optional-chaining', ['@babel/plugin-proposal-decorators', { legacy: true }], ['@babel/plugin-proposal-class-properties', { loose: false }], isDev() ? 'react-refresh/babel' : null, ].filter((t) => t), cacheDirectory: isProd(), }; module.exports = { plugins: { HtmlWebpackPlugin, MiniCssExtractPlugin, CopyWebpackPlugin, CssMinimizerPlugin, TerserPlugin, UselessFilesCleanWebpackPlugin, CompressionPlugin, }, config: { /** * 入口 */ entry: { // 判断入口文件是.js,.jsx,.tsx index: Util.getEntryIndex(runtimePath), }, /** * 出口 */ output: { filename: isProd() ? '[name].[chunkhash].bundle.js' : '[name].[contenthash].bundle.js', chunkFilename: isProd() ? '[name].[chunkhash].bundle.js' : '[name].[contenthash].bundle.js', path: path.resolve(runtimePath, 'dist'), publicPath: '/', clean: true, }, plugins: (isProd() ? [ new webpack.optimize.ModuleConcatenationPlugin(), new CompressionPlugin({ algorithm: 'gzip', test: new RegExp('\\.(' + ['js', 'css'].join('|') + ')$'), threshold: 10240, minRatio: 0.8, }), ] : [] ).concat([ new HtmlWebpackPlugin({ title: '', filename: 'index.html', template: path.join(runtimePath, 'src', 'index.html'), hash: true, // 防止缓存 minify: { removeAttributeQuotes: true, // 压缩 去掉引号 }, chunks: ['index'], }), // new webpack.HashedModuleIdsPlugin(), new MiniCssExtractPlugin({ filename: isDev() ? '[name].css' : '[name].[contenthash].css', chunkFilename: isDev() ? '[name].css' : '[name].[contenthash].css', ignoreOrder: false, }), new webpack.ProvidePlugin({ _: 'lodash', $: 'jquery', }), new ForkTsCheckerWebpackPlugin({ typescript: { configFile: path.join(runtimePath, 'tsconfig.json'), // checkSyntacticErrors: true, }, }), new WebpackBar({ reporters: ['profile'], profile: true }), new UselessFilesCleanWebpackPlugin({ root: APP_PATH, out: path.join(runtimePath, 'lessFiles'), clean: false, exclude: ['*.gitignore', 'node_modules'], log: 'console', }), ]), optimization: isDev() ? { splitChunks: false, } : { minimize: !isDev(), // true, minimizer: isDev() ? [] : [new TerserPlugin(), new CssMinimizerPlugin()], runtimeChunk: 'single', splitChunks: { cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', chunks: 'all', }, }, }, }, module: { rules: [ { test: /\.m?jsx?$/, exclude: /(node_modules|bower_components)/, // include: [APP_PATH], use: [ ...devLoaders, { loader: 'babel-loader', options: babelConfig, }, ], }, { test: /\.m?tsx?$/, exclude: /(node_modules|bower_components)/, // include: [APP_PATH], use: [ ...devLoaders, { loader: 'babel-loader', options: babelConfig, }, { loader: 'ts-loader', options: { transpileOnly: true, happyPackMode: true, configFile: path.join(runtimePath, 'tsconfig.json'), }, }, ], }, { test: /\.css$/, include: [ APP_PATH, /highlight.js/, /photoswipe.css/, /default-skin.css/, /swiper.min.css/, /antd/, /antd-mobile/, /normalize.css/, ], use: [ isDev() ? 'style-loader' : { loader: MiniCssExtractPlugin.loader, }, { loader: 'css-loader', options: { importLoaders: 1, }, }, { loader: 'postcss-loader', options: { postcssOptions: { config: getPostCssConfigPath(runtimePath), }, }, }, ], }, { test: /\.less$/, include: [APP_PATH, /normalize.less/], use: [ isDev() ? 'style-loader' : { loader: MiniCssExtractPlugin.loader, }, { loader: 'css-loader', options: { importLoaders: 1, }, }, { loader: 'postcss-loader', options: { postcssOptions: { config: getPostCssConfigPath(runtimePath), }, }, }, { loader: 'less-loader', options: { lessOptions: { javascriptEnabled: true, }, }, }, ], }, { test: /\.(png|svg|jpg|gif|ico)$/, type: 'asset/resource', }, { test: /\.(woff|woff2|eot|ttf|otf)$/, type: 'asset/resource', }, { test: /\.(csv|tsv)$/, use: ['csv-loader'], }, { test: /\.xml$/, use: ['xml-loader'], }, { test: /\.ejs/, use: [ { loader: 'ejs-loader', options: { variable: 'data', }, }, ], }, { test: /\.ya?ml$/, use: ['json-loader', 'yaml-loader'], }, { test: /\.md$/, use: ['raw-loader'], }, ], }, resolve: { modules: [/* path.join(runtimePath, 'node_modules'), */ 'node_modules'], extensions: ['.js', '.jsx', '.ts', '.tsx', '.css', '.less', '.sass', '.json'], // 后缀名自动补全 }, }, };