说明
玩转webpack学习笔记
功能模块设计
可以看下图:
目录结构设计
- lib 放置源代码
- test 放置测试代码
+ |- /test + |- /lib + |- webpack.dev.js + |- webpack.prod.js + |- webpack.ssr.js + |- webpack.base.js + |- README.md + |- CHANGELOG.md + |- .eslinrc.js + |- package.json + |- index.js
实战:搭建构建包
新建项目文件
1、先利用 npm init -y
生成 package.json
文件,然后添加 builder-webpack
文件夹,以及 lib
、test
文件夹,然后在 lib
文件夹里添加4个配置文件。
webpack.base.js 配置
根据构建包的功能划分, webpack.base.js
配置如下:
const autoprefixer = require('autoprefixer'); const glob = require('glob'); const path = require('path'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const projectRoot = process.cwd(); const setMPA = () => { const entry = {}; const htmlWebpackPlugins = []; const entryFiles = glob.sync(path.join(projectRoot, './src/*/index.js')); Object.keys(entryFiles) .map((index) => { const entryFile = entryFiles[index]; // '/Users/cpselvis/my-project/src/index/index.js' const match = entryFile.match(/src\/(.*)\/index\.js/); const pageName = match && match[1]; entry[pageName] = entryFile; return htmlWebpackPlugins.push( new HtmlWebpackPlugin({ inlineSource: '.css$', template: path.join(projectRoot, `./src/${pageName}/index.html`), filename: `${pageName}.html`, chunks: ['vendors', pageName], inject: true, minify: { html5: true, collapseWhitespace: true, preserveLineBreaks: false, minifyCSS: true, minifyJS: true, removeComments: false, }, }) ); }); return { entry, htmlWebpackPlugins, }; }; const { entry, htmlWebpackPlugins } = setMPA(); module.exports = { entry: entry, output: { path: path.join(projectRoot, 'dist'), filename: '[name]_[chunkhash:8].js' }, module: { rules: [ { test: /.js$/, use: [ { loader: 'babel-loader' } ], }, { test: /.css$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', ], }, { test: /.less$/, use: [ MiniCssExtractPlugin.loader, 'css-loader', 'less-loader', { loader: 'postcss-loader', options: { plugins: () => [ autoprefixer({ browsers: ['last 2 version', '>1%', 'ios 7'], }), ], }, }, { loader: 'px2rem-loader', options: { remUnit: 75, remPrecision: 8, }, }, ], }, { test: /.(png|jpg|gif|jpeg)$/, use: [ { loader: 'file-loader', options: { name: '[name]_[hash:8].[ext]', }, }, ], }, { test: /.(woff|woff2|eot|ttf|otf)$/, use: [ { loader: 'file-loader', options: { name: '[name]_[hash:8][ext]', }, }, ], }, ], }, plugins: [ new MiniCssExtractPlugin({ filename: '[name]_[contenthash:8].css', }), new CleanWebpackPlugin(), new FriendlyErrorsWebpackPlugin(), function errorPlugin() { this.hooks.done.tap('done', (stats) => { if (stats.compilation.errors && stats.compilation.errors.length && process.argv.indexOf('--watch') === -1) { process.exit(1); } }); }, ].concat(htmlWebpackPlugins), stats: 'errors-only', };
webpack.dev.js 配置
根据构建包的功能划分, webpack.dev.js
配置如下:
配置里用到了 webpack-merge
,我们需要安装一下依赖
npm i webpack-merge -D
const merge = require('webpack-merge'); const webpack = require('webpack'); const baseConfig = require('./webpack.base'); const devConfig = { mode: 'production', plugins: [ new webpack.HotModuleReplacementPlugin(), ], devServer: { contentBase: './dist', hot: true, stats: 'errors-only', }, devtool: 'cheap-source-map', }; module.exports = merge(baseConfig, devConfig);
webpack.prod.js 配置
根据构建包的功能划分, webpack.prod.js
配置如下:
const cssnano = require('cssnano'); const merge = require('webpack-merge'); const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin'); const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); const baseConfig = require('./webpack.base'); const prodConfig = { mode: 'production', plugins: [ new OptimizeCSSAssetsPlugin({ assetNameRegExp: /\.css$/g, cssProcessor: cssnano, }), new HtmlWebpackExternalsPlugin({ externals: [ { module: 'react', entry: 'https://11.url.cn/now/lib/16.2.0/react.min.js', global: 'React', }, { module: 'react-dom', entry: 'https://11.url.cn/now/lib/16.2.0/react-dom.min.js', global: 'ReactDOM', }, ], }), ], optimization: { splitChunks: { minSize: 0, cacheGroups: { commons: { name: 'vendors', chunks: 'all', minChunks: 2, }, }, }, }, }; module.exports = merge(baseConfig, prodConfig);
webpack.ssr.js 配置
根据构建包的功能划分, webpack.ssr.js
配置如下:
const cssnano = require('cssnano'); const merge = require('webpack-merge'); const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin'); const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); const baseConfig = require('./webpack.base'); const prodConfig = { mode: 'production', module: { rules: [ { test: /\.css$/, use: 'ignore-loader', }, { test: /\.less$/, use: 'ignore-loader', }, ], }, plugins: [ new OptimizeCSSAssetsPlugin({ assetNameRegExp: /\.css$/g, cssProcessor: cssnano, }), new HtmlWebpackExternalsPlugin({ externals: [ { module: 'react', entry: 'https://11.url.cn/now/lib/16.2.0/react.min.js', global: 'React', }, { module: 'react-dom', entry: 'https://11.url.cn/now/lib/16.2.0/react-dom.min.js', global: 'ReactDOM', }, ], }), ], optimization: { splitChunks: { minSize: 0, cacheGroups: { commons: { name: 'commons', chunks: 'all', minChunks: 2, }, }, }, }, }; module.exports = merge(baseConfig, prodConfig);