在模块化的开发过程中我们经常会使用webpack来帮助我们搭建一个良好的开发环境,提升开发效率;很多人对webpack的那么多配置项感到无从下手,下面是我总结的如何构建一个简单的webpack配置。
准备工作
先看一下我们一个简单的webpack配置大概需要的目录结构,暂时我们只处理核心的build和config部分
build目录
基础配置
<!--webpack.base.conf.js-->
var path = require('path');
// 清空dist目录下面文件
var CleanWebpackPlugin = require('clean-webpack-plugin');
// 生成html静态文件
var HtmlWebpackPlugin = require('html-webpack-plugin');
// 提取静态文件
var CopyWebpackPlugin = require('copy-webpack-plugin')
var webpack = require('webpack');
module.exports = {
// 基础目录,绝对路径,用于从配置中解析入口起点(entry point)和 loader
context: path.resolve(__dirname, "../"),
entry: {
// babel的兼容包
// app: ['babel-polyfill', './src/index.js'],
app: './src/main.js',
},
output: {
path: path.resolve(__dirname, '../dist'),
// 代码分离出口配置项
filename: 'static/js/[name].[hash].bundle.js',
// 针对于loader的resolve配置
}
// Resolve 配置 Webpack 如何寻找模块所对应的文件
resolve: {
// 1. 添加为一个可解析的扩展名
// 2. 能够使用户在引入模块时不带扩展:import SomeFile from "./somefile"
extensions: ['.', '.ts', '.js', 'jsx', '.json', '.vue', 'styl'],
// 设置目录别名
alias: {
// 配置vue在编译build时使用,不设置只能在runtime使用
'vue$': 'vue/dist/vue.esm.js',
'@': path.resolve(__dirname, '../src'),
},
// 用户描述的json文件名
// descriptionFiles: ["package.json"],
// 解析目录时要使用的文件名
mainFiles: ["index"],
// webpack 解析模块时应该搜索的目录。
modules: ["node_modules"],
},
module: {
rules: [
{
test: /\.js$/,
// loader包含的文件, 不设置默认package.json统计目录下的所有文件
include: [path.resolve(__dirname, '../src')],
// loader不包含的文件
exclude: [/node-modules/],
use: [
// 使用happypack后无法使用thread-loader
{
loader: 'thread-loader'
},
{
loader: 'babel-loader',
options: {
cacheDirectory: true, // 开启缓存
compact: false // 不压缩
},
}
]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
limit: 10000,
name: 'static/img/[name].[hash:7].[ext]',
}
}
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader',
options: {
limit: 10000,
name: 'static/fonts/[name].[hash:7].[ext]',
}
}
]
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
use: [
{
loader: 'file-loader',
options: {
limit: 10000,
name: 'static/media/[name].[hash:7].[ext]',
}
}
]
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, '../dist/index.html'),
template: 'index.html',
inject: true,
}),
};
开发环境配置
<!--webpack.dev.conf.js-->
var path = require('path');
var webpack = require('webpack');
var merge = require('webpack-merge');
var common = require('./webpack.base.conf.js');
// 引入环境变量
var config = require('../config')
module.exports = merge(common, {
mode: 'development',
// 开发工具使用原始代码
// devtool: 'source-map',
devtool: 'cheap-module-eval-source-map',
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
],
},
]
},
devServer: {
// 你要提供哪里的内容给虚拟服务器用。这里最好填 绝对路径。默认当前目录
contentBase: [path.join(__dirname, "../dist")],
// 热模块更新 webpack.HotModuleReplacementPlugin (HMR)
hot: true,
// 控制浏览器控制台消息 none, error, warning 或者 error
clientLogLevel: "warning",
// 如果为 true ,页面出错不会弹出 404 页面。
historyApiFallback: true,
// 自动打开浏览器
open: true,
// 索引文件的文件名
index: 'index.htm',
// 使用ip访问
useLocalIp: true,
watchOptions: {
//不监听的文件或者文件夹,支持正则匹配 监听大量文件系统会导致大量的 CPU 或内存占用
//默认为空
ignored: /node_modules/,
//监听到变化发生后会等300ms再去执行动作,防止文件更新太快
//默认为300ms
aggregateTimeout: 100,
//判断文件是否发生变化是通过不停询问系统指定文件有没有变化实现的
//默认每秒问1000次
poll: 1000
},
},
plugins: [
new webpack.DefinePlugin({
'process.env': config.development.envObj
}),
new webpack.HotModuleReplacementPlugin(), // 开启HMR 模块热替换
new webpack.NamedModulesPlugin(), // 开启 HMR的时候使用该插件会显示模块的相对路径
new webpack.NoEmitOnErrorsPlugin(), // webpack跳过编译错误
]
});
生产环境配置
<!--webpack.prod.conf.js-->
var path = require('path');
var webpack = require('webpack');
var merge = require('webpack-merge');
// 提取css
var MiniCssExtractPlugin = require('mini-css-extract-plugin');
// webpack打包依赖
var common = require('./webpack.base.conf.js');
var TerserPlugin = require('terser-webpack-plugin');
module.exports = smp.wrap(merge(common, {
// 开启多进程编译并开启缓存
optimization: {
minimizer: [
new TerserPlugin({
cache: true,
parallel: true,
}),
],
},
mode: 'production',
devtool: false, // 生产环境不使用sourceMap'
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
],
},
]
},
plugins: [
// 优化点 代码分离css
new MiniCssExtractPlugin({
filename: 'static/css/[name].[contenthash].css',
}),
],
})
)
打包配置
<!--build.js-->
var webpack = require('webpack');
var config = require('../config')
var configBuild = require('./webpack.prod.conf')
var merge = require('webpack-merge');
var env = process.argv.filter((val, index, array) => {
return index >= 2
})[0];
var setEnv = {
plugins: [
new webpack.DefinePlugin({
'process.env': config[env].envObj
}),
]
}
var obj = merge(configBuild, setEnv)
var compiler = webpack(obj);
compiler.run((err, stats) => {
console.log(stats.toString({
colors: true,
// 不显示模块信息
modules: false,
children: false,
chunks: false,
chunkModules: false
}));
});
config目录
环境变量配置
module.exports = {
// 环境变量配置
development: {
envObj: {
NODE_ENV: '"development"',
API_HOST: '"http://xxx.xxx.xx.x:xxxx"',
API_IMG: '"http://xxx.xxx.xx.x:xxxx"',
}
},
production: {
envObj: {
NODE_ENV: '"production"',
API_HOST: '"http://xxx.xxx.xx.x:xxxx"',
API_IMG: '"http://xxx.xxx.xx.x:xxxx"'
}
},
test: {
envObj: {
NODE_ENV: '"test"',
API_HOST: '"http://xxx.xxx.xx.x:xxxx"',
API_IMG: '"http://xxx.xxx.xx.x:xxxx"'
}
},
}
- 针对于不懂的配置,代码中大都有注释,Vue,React项目大都可以在此基础上进行简单扩展使用;
- 有时间会附上Vue配置和React配置
- 如需了解webpack如何优化 点击查看