Skip to content

《深入浅出Webpack》前端构建系列 02:配置速查——从Entry到DevServer全维度配置解析

约 5458 字大约 18 分钟

《深入浅出Webpack》前端构建系列Webpack

2026-04-04

本文是《深入浅出Webpack》前端构建系列的第二篇,聚焦Webpack核心配置体系的全维度解析,涵盖Entry、Output、Module、Resolve等核心配置项的定义、用法、参数及实操案例。学完本文后,你将能熟练掌握Webpack各类配置的设计逻辑与落地方法,快速搭建符合项目需求的Webpack配置体系。

【本篇核心收获】

  • 掌握Webpack两种配置方式及配置项的分类逻辑,明确不同配置项的作用范围
  • 精通Entry配置的多类型用法(静态/动态)、Chunk命名规则及context的核心作用
  • 吃透Output配置的文件名模板、路径、公共URL、库导出等关键参数的配置逻辑
  • 熟练配置Module规则(Loader、noParse、parser),掌握Loader的匹配与执行顺序控制
  • 理解Resolve模块解析规则,能通过别名、后缀、模块目录等配置优化导入逻辑
  • 掌握Plugin、DevServer及其他零散配置项(target、devtool、externals等)的核心用法

2.0 配置概述

Webpack的配置是实现构建能力定制化的核心,其配置方式主要分为两种:

  1. 配置文件式:通过JavaScript文件(如webpack.config.js)描述配置;
  2. 命令行参数式:执行Webpack可执行文件时传入参数(如webpack --devtool source-map)。

两种方式可搭配使用,例如webpack --config webpack-dev.config.js指定配置文件,再在文件内补充配置。

按配置方式划分,配置项可分为三类:

  • 仅命令行参数传入的选项(极少);
  • 仅配置文件配置的选项;
  • 两种方式均可配置的选项。

按配置功能划分,核心类别包括:Entry(入口)、Output(输出)、Module(模块规则)、Resolve(模块解析)、Plugins(插件)、DevServer(开发服务器)、其他配置项、整体配置结构、多种配置类型、配置总结。

模块小结:Webpack配置支持文件与命令行两种方式,配置项按功能可划分为8大核心类别,明确分类逻辑是高效配置的基础。

2.1 Entry(模块入口配置)

Entry是Webpack执行构建的起点,用于配置模块的入口,是必填项(不配置会导致Webpack报错退出),其核心作用是让Webpack从入口开始,递归解析所有依赖的模块。

2.1.1 context(入口解析根目录)

Webpack寻找相对路径文件时,会以context为根目录,默认值为启动Webpack时的当前工作目录。若需修改,需配置为绝对路径:

module.exports = {
  context: path.resolve(__dirname, 'app')
};

也可通过命令行webpack --context设置context。context会影响Entry路径及依赖模块路径的解析,是入口配置的前置基础。

2.1.2 Entry类型

Entry支持三种核心类型,可单独使用或组合,具体如下:

类型例子含义
string'./app/entry'入口模块的文件路径(可相对路径)
array['./app/entry1', './app/entry2']入口模块的文件路径列表(可相对路径)
object{a:'./app/entry-a', b:['./app/entry-b1', './app/entry-b2']}多入口配置,每个入口生成一个Chunk

注意:array类型搭配output.library使用时,仅数组最后一个入口文件的模块会被导出。

2.1.3 Chunk的名称

Webpack会为每个生成的Chunk分配名称,名称规则与Entry配置直接相关:

  • Entry为string/array时,仅生成一个Chunk,名称为main
  • Entry为object时,生成多个Chunk,名称为object键值对的键名。

2.1.4 配置动态Entry

若项目页面数量动态增长,静态Entry配置无法适配,可将Entry设为函数,动态返回配置:

// 同步函数
entry: () => {
  return {
    a: './pages/a',
    b: './pages/b',
  };
};

// 异步函数
entry: () => {
  return new Promise((resolve) => {
    resolve({
      a: './pages/a',
      b: './pages/b',
    });
  });
};

模块小结:Entry作为构建起点,context定义相对路径解析根目录;支持string/array/object三种静态类型,及同步/异步函数的动态配置;Chunk名称由Entry类型决定,动态Entry可适配页面数量变化的场景。

2.2 Output(构建输出配置)

Output是Object类型配置项,用于定义如何输出最终构建的代码,涵盖文件名、路径、公共URL等核心参数。

2.2.1 filename(输出文件名)

filename为string类型,用于配置输出文件的名称:

  • 单输出文件:可配置为静态值(如filename: 'bundle.js');
  • 多Chunk输出:需借助模板变量区分(如filename: '[name].js')。

Webpack内置了多个变量用于文件名模板,核心如下:

变量名含义
idChunk 的唯一标识(从0开始)
nameChunk 的名称
hashChunk 唯一标识的Hash值
chunkhashChunk 内容的Hash值

Hash长度可指定(如[hash:8]取8位,默认20位)。

注意:ExtractTextWebpackPlugin插件使用contenthash而非chunkhash,原因是该插件提取的是代码内容本身,而非模块组成的Chunk。

2.2.2 chunkFilename(无入口Chunk文件名)

chunkFilename用于配置运行过程中生成的无入口Chunk的输出名称(如CommonChunkPlugin、动态导入import('path/to/module')生成的Chunk),支持与filename相同的内置变量。

2.2.3 path(输出目录)

path用于配置输出文件的本地存储目录,必须为绝对路径,通常结合Node.js的path模块配置:

path: path.resolve(__dirname, 'dist[hash]');

2.2.4 publicPath(线上资源URL前缀)

publicPath为string类型,用于配置发布到线上的资源URL前缀,默认值为空字符串(相对路径)。若需将资源上传至CDN,配置示例如下:

filename:'[name].[chunkhash:8].js',
publicPath:'https://cdn.example.com/assets/'

此时线上HTML引入JS文件的路径为:

<script src='https://cdn.example.com/assets/a_12345678.js'></script>

注意:publicPath配置错误会导致资源加载404,需谨慎设置。path和publicPath均支持字符串模板,内置变量仅hash(一次编译的Hash值)。

2.2.5 crossOriginLoading(异步加载跨域配置)

Webpack异步加载Chunk基于JSONP实现(动态插入<script>标签),crossOriginLoading用于配置该标签的crossorigin属性,可选值:

  • anonymous(默认):加载脚本时不带用户Cookies;
  • use-credentials:加载脚本时携带用户Cookies。

该配置常用于获取异步脚本执行的详细错误信息。

2.2.6 libraryTarget 和 library(库导出配置)

当构建可被其他模块导入的库时,需搭配使用这两个配置:

  • libraryTarget:string枚举类型,配置库的导出方式;
  • library:string类型,配置导出库的名称。

libraryTarget的核心取值及对应导出逻辑如下:

取值输出代码示例(library='LibraryName')使用方式示例
var(默认)var LibraryName = lib_code;LibraryName.doSomething();
commonjsexports['LibraryName'] = lib_code;require['library-name-in-npm']('LibraryName').doSomething();
commonjs2module.exports = lib_code;require('library-name-in-npm').doSomething();
thisthis['LibraryName'] = lib_code;this.LibraryName.doSomething();
windowwindow['LibraryName'] = lib_code;window.LibraryName.doSomething();
globalglobal['LibraryName'] = lib_code;global.LibraryName.doSomething();

注意libraryTarget为commonjs2时,library配置无意义;commonjs2与commonjs的区别是增加了module.exports导出方式。

2.2.7 libraryExport(库子模块导出)

仅当libraryTarget为commonjs/commonjs2时生效,用于配置导出库中需要暴露的子模块。例如原模块代码:

export const a = 1;
export default b = 2;

若配置libraryExport: 'a',则输出代码为:

module.exports = lib_code['a'];

使用时require('library-name-in-npm') === 1

模块小结:Output配置决定构建产物的输出形态,filename/chunkFilename通过内置变量适配多Chunk场景,path指定本地输出目录,publicPath控制线上资源访问路径,library相关配置专为库开发设计,可灵活控制导出方式。

2.3 Module(模块处理规则)

Module用于配置处理模块的规则,核心是Loader配置,同时包含noParse、parser等性能与语法控制项。

2.3.1 配置Loader

rules是Module的核心配置,为数组类型,每一项描述一组文件的处理规则,配置逻辑分为三步:

  1. 条件匹配:通过test(匹配文件)、include(命中目录)、exclude(排除目录)选中目标文件;
  2. 应用规则:通过use配置Loader,可单Loader或多Loader(从后往前执行),支持传入参数;
  3. 重置顺序:通过enforce(pre/post)调整Loader执行顺序(最前/最后)。

配置示例

module: {
  rules: [
    // 处理JavaScript文件
    {
      test: /\.js$/,
      use: ['babel-loader?cacheDirectory'], // cacheDirectory缓存编译结果
      include: path.resolve(__dirname, 'src'), // 仅命中src目录
    },
    // 处理SCSS文件
    {
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 'sass-loader'], // 执行顺序:sass-loader → css-loader → style-loader
      exclude: path.resolve(__dirname, 'node_modules'), // 排除node_modules
    },
    // 处理非文本文件
    {
      test: /\.(gif|png|jpe?g|eot|woff|ttf|svg|pdf)$/,
      use: ['file-loader'],
    }
  ];
}

Loader参数较多时,可通过Object形式配置:

use: [
  {
    loader: 'babel-loader',
    options: {
      cacheDirectory: true,
    },
    enforce: 'post', // 执行顺序放最后
  }
];

test/include/exclude均支持数组类型(项之间为“或”关系):

{
  test: [/\.jsx?$/, /\.tsx?$/],
  include: [
    path.resolve(__dirname, 'src'),
    path.resolve(__dirname, 'tests'),
  ],
  exclude: [
    path.resolve(__dirname, 'node_modules'),
    path.resolve(__dirname, 'bower_components'),
  ],
}

2.3.2 noParse(忽略非模块化文件解析)

noParse用于让Webpack忽略对部分非模块化文件的递归解析,可提升构建性能(如jQuery、ChartJS等无模块化语句的大库)。支持RegExp、[RegExp]、function类型:

// 正则形式
noParse: /jquery|chartjs/;

// 函数形式(Webpack 3.0.0+支持)
noParse: (content) => {
  return /jquery|chartjs/.test(content); // content为模块文件路径
};

注意:被忽略的文件不能包含import/require/define等模块化语句,否则构建后代码会包含浏览器无法执行的模块化语句。

2.3.3 parser(模块化语法解析控制)

parser用于细粒度控制模块化语法的解析(区别于noParse的文件级忽略),支持禁用特定模块化语法:

module: {
  rules: [
    {
      test: /\.js$/,
      use: ['babel-loader'],
      parser: {
        amd: false, // 禁用AMD
        commonjs: false, // 禁用CommonJS
        system: false, // 禁用SystemJS
        harmony: false, // 禁用ES6 import/export
        requireInclude: false, // 禁用require.include
        requireEnsure: false, // 禁用require.ensure
        requireContext: false, // 禁用require.context
        browserify: false, // 禁用browserify
        requireJs: false, // 禁用requirejs
      },
    },
  ];
}

模块小结:Module配置核心是Loader规则,通过test/include/exclude精准匹配文件,控制Loader执行顺序与参数;noParse提升非模块化文件的构建性能,parser精细控制模块化语法解析,三者结合可实现模块处理的定制化。

2.4 Resolve(模块解析规则)

Resolve用于配置Webpack寻找模块的规则,Webpack内置模块化语法解析功能,默认遵循模块化标准约定,也可通过Resolve定制解析逻辑。

2.4.1 alias(模块别名)

alias用于将原导入路径映射为新路径,简化导入语句:

resolve: {
  alias: {
    components: './src/components/', // 替换components关键字
  },
}

此时import Button from 'components/button'等价于import Button from './src/components/button'

若需精准匹配(仅命中以关键字结尾的导入),可添加$

resolve: {
  alias: {
    'react$': '/path/to/react.min.js', // 仅替换import 'react'
  },
}

2.4.2 mainFields(第三方模块入口优先级)

部分第三方模块会为不同环境提供多份代码(如ES5/ES6),入口信息写在package.json中:

{
  "jsnext:main": "es/index.js", // ES6代码入口
  "main": "lib/index.js" // ES5代码入口
}

Webpack会按mainFields的顺序查找package.json,取第一个匹配的入口,默认配置:

mainFields: ['browser', 'main'];

若需优先使用ES6代码,配置:

mainFields: ['jsnext:main', 'browser', 'main'];

2.4.3 extensions(无后缀导入的后缀匹配)

导入语句无文件后缀时,Webpack会自动拼接后缀尝试访问文件,extensions配置匹配列表,默认:

extensions: ['.js', '.json'];

例如require('./data')会先找./data.js,再找./data.json,找不到则报错。

若需优先匹配TypeScript文件,配置:

extensions: ['.ts', '.js', '.json'];

2.4.4 modules(第三方模块查找目录)

modules配置Webpack寻找第三方模块的目录,默认仅node_modules。若项目内有大量复用模块(如./src/components),可配置:

modules: ['./src/components', 'node_modules'];

此时import 'button'即可导入./src/components/button,无需冗长的相对路径。

2.4.5 descriptionFiles(第三方模块描述文件)

配置描述第三方模块的文件名称,默认:

descriptionFiles: ['package.json'];

2.4.6 enforceExtension(强制导入带后缀)

若配置为true,所有导入语句必须带文件后缀,例如import '/foo'需改为import '/foo.js'

2.4.7 enforceModuleExtension(第三方模块后缀豁免)

与enforceExtension搭配使用,enforceExtension: true时,第三方模块导入语句多无后缀,可配置:

enforceModuleExtension: false;

豁免node_modules下的模块,避免报错。

模块小结:Resolve配置通过别名、入口优先级、后缀匹配、查找目录等规则,优化模块解析逻辑,可大幅简化导入语句,提升开发效率与构建性能。

2.5 Plugin(扩展功能配置)

Plugin用于扩展Webpack的功能,几乎可实现所有与构建相关的定制化需求。plugins配置为数组,每一项是Plugin的实例,参数通过构造函数传入:

const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');

module.exports = {
  plugins: [
    // 提取公共代码到common Chunk
    new CommonsChunkPlugin({
      name: 'common',
      chunks: ['a', 'b'],
    }),
  ],
};

核心注意:Plugin配置的难点在于掌握具体插件的参数,而非接入方式;社区插件可覆盖绝大多数Webpack原生不支持的功能,需善于通过搜索引擎寻找解决方案。

模块小结:Plugin是Webpack功能扩展的核心,通过实例化插件并传入参数即可集成扩展能力,社区生态是Plugin使用的关键。

2.6 DevServer(开发服务器配置)

DevServer用于提升开发效率,其配置仅在通过DevServer启动Webpack时生效(Webpack本身不识别devServer配置),支持配置文件(devServer字段)和命令行参数两种方式。

2.6.1 hot(模块热替换)

配置是否启用模块热替换(HMR),DevServer默认通过刷新整个页面实现实时预览,开启HMR后,可在不刷新页面的情况下替换老模块,实现精准更新。

2.6.2 inline(代理客户端注入)

DevServer的实时预览依赖注入页面的代理客户端,inline配置是否自动注入该客户端(默认开启):

  • 开启inline:DevServer通过代理客户端控制页面刷新;
  • 关闭inline:DevServer通过iframe运行页面,需访问http://localhost:8080/webpack-dev-server/预览,构建后刷新iframe。

注意:使用HMR实现实时预览,最便捷的方式是开启inline。

2.6.3 historyApiFallback(HTML5 History API适配)

适配使用HTML5 History API的单页应用,让服务器对任意路由请求返回指定HTML文件:

  • 简单配置(单HTML文件):

    historyApiFallback: true; // 所有请求返回index.html
  • 多HTML文件配置:

    historyApiFallback: {
      rewrites: [
        { from: /^\/user/, to: '/user.html' }, // /user开头返回user.html
        { from: /^\/game/, to: '/game.html' }, // /game开头返回game.html
        { from: /./, to: '/index.html' }, // 其他返回index.html
      ],
    };

2.6.4 contentBase(静态文件根目录)

配置DevServer HTTP服务器的静态文件根目录,默认是当前执行目录。若需暴露项目根目录下的public目录:

devServer: {
  contentBase: path.join(__dirname, 'public'),
}

注意:DevServer暴露文件分为两类——本地文件(由contentBase控制)、Webpack构建产物(无本地文件);可通过contentBase: false关闭本地文件暴露。

2.6.5 headers(HTTP响应头注入)

在HTTP响应中注入自定义响应头:

devServer: {
  headers: {
    'X-foo': 'bar',
  },
}

2.6.6 host(监听地址)

配置DevServer的监听地址,仅支持命令行参数传入,默认127.0.0.1(仅本地访问)。若需局域网设备访问,启动时传入--host 0.0.0.0

2.6.7 port(监听端口)

配置监听端口,默认8080;若端口被占用,自动依次尝试8081、8082等。

2.6.8 allowedHosts(请求HOST白名单)

仅允许白名单内的HOST请求正常返回:

allowedHosts: [
  'host.com', // 匹配单个域名
  'sub.host.com',
  '.host2.com', // 匹配host2.com及所有子域名
];

2.6.9 disableHostCheck(关闭HOST检查)

默认仅接收本地请求,关闭后可接收任意HOST的请求,通常搭配--host 0.0.0.0使用(通过IP访问本地服务)。

2.6.10 https(HTTPS服务配置)

DevServer默认使用HTTP,可配置为HTTPS(如HTTP/2、Service Worker场景必需):

  • 自动生成证书:

    devServer: {
      https: true,
    }
  • 自定义证书:

    devServer: {
      https: {
        key: fs.readFileSync('path/to/server.key'),
        cert: fs.readFileSync('path/to/server.crt'),
        ca: fs.readFileSync('path/to/ca.pem'),
      },
    }

2.6.11 clientLogLevel(客户端日志等级)

配置浏览器开发者工具控制台的日志等级,可选值:none(无日志)、error(仅错误)、warning(错误+警告)、info(所有,默认)。

2.6.12 compress(Gzip压缩)

布尔类型,配置是否启用Gzip压缩,默认false。

2.6.13 open(自动打开浏览器)

DevServer启动并完成第一次构建后,自动用系统默认浏览器打开开发页面;可通过openPage配置打开指定URL。

模块小结:DevServer配置聚焦开发效率提升,涵盖热替换、路由适配、静态文件服务、网络配置等维度,合理配置可大幅降低开发过程中的环境调试成本。

2.7 其他配置项

除核心配置外,Webpack还提供了若干零散配置项,覆盖运行环境、调试、文件监听、外部模块等场景。

2.7.1 target(运行环境适配)

配置Webpack构建代码的目标运行环境,核心取值如下:

target值描述
web针对浏览器(默认),代码集中在一个文件
node针对Node.js,保留require加载Chunk
async-node针对Node.js,异步加载Chunk
webworker针对WebWorker
electron-main针对Electron主线程
electron-renderer针对Electron渲染线程

例如target: 'node'时,require('fs')会被保留,fs模块不会被打包到Chunk中。

2.7.2 devtool(Source Map生成)

配置Source Map的生成方式,默认false(不生成)。若需生成Source Map便于调试:

module.exports = {
  devtool: 'source-map',
};

2.7.3 Watch和WatchOptions(文件监听)

Watch用于开启文件监听模式(文件变化时重新编译),默认关闭;DevServer下默认开启:

module.exports = {
  watch: true, // 开启监听
  watchOptions: {
    ignored: /node_modules/, // 忽略监听目录
    aggregateTimeout: 300, // 监听到变化后延迟300ms执行(避免高频编译)
    poll: 1000, // 每秒询问1000次文件是否变化
  },
};

2.7.4 externals(外部模块忽略打包)

告诉Webpack忽略指定模块的打包,使用运行环境中已存在的全局变量/模块,避免重复打包。例如页面中已通过<script>引入jQuery:

<script src="path/to/jquery.js"></script>

配置externals后,源码中import $ from 'jquery'不会将jQuery打包到Chunk中:

module.exports = {
  externals: {
    jquery: 'jQuery', // 导入语句的jquery替换为全局变量jQuery
  },
};

2.7.5 resolveLoader(Loader查找规则)

配置Webpack寻找Loader的规则,默认配置:

module.exports = {
  resolveLoader: {
    modules: ['node_modules'],
    extensions: ['.js', '.json'],
    mainFields: ['loader', 'main'],
  },
};

常用于加载本地自定义Loader。

模块小结:其他配置项覆盖运行环境、调试、文件监听、外部模块等场景,是Webpack配置体系的重要补充,可根据项目需求灵活调整。

2.8 整体配置结构

Webpack的完整配置结构清晰涵盖所有核心维度,以下是标准化的配置结构参考(含关键注释):

const path = require('path');

module.exports = {
  // 入口配置
  entry: './app/entry', // 单入口(string)
  // entry: ['./app/entry1', './app/entry2'], // 单入口(array)
  // entry: { a: './app/entry-a', b: ['./app/entry-b1', './app/entry-b2'] }, // 多入口(object)

  // 输出配置
  output: {
    path: path.resolve(__dirname, 'dist'), // 输出目录(绝对路径)
    filename: 'bundle.js', // 单文件输出
    // filename: '[name].js', // 多Chunk输出(按名称)
    // filename: '[chunkhash].js', // 按内容Hash输出
    publicPath: '/assets/', // 线上资源URL前缀
    // publicPath: 'https://cdn.example.com/', // CDN前缀
    library: 'MyLibrary', // 导出库名称
    libraryTarget: 'umd', // 库导出方式
  },

  pathinfo: true, // 包含文件路径信息到生成代码
  chunkFilename: '[id].js', // 无入口Chunk文件名
  jsonpFunction: 'myWebpackJsonp', // JSONP回调函数名
  sourceMapFilename: '[file].map', // Source Map文件名
  devtoolModuleFilenameTemplate: 'webpack:/// [resource-path]', // 开发者工具中源码模块名称
  crossOriginLoading: 'anonymous', // 异步加载跨域方式

  // 模块规则
  module: {
    rules: [
      {
        test: /\.jsx?$/, // 匹配文件
        include: [path.resolve(__dirname, 'app')], // 命中目录
        exclude: [path.resolve(__dirname, 'app/demo-files')], // 排除目录
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {}, // Loader参数
          },
        ],
      },
    ],
    noParse: [/special-library\.js$/], // 忽略解析的模块
  },

  // 插件配置
  plugins: [],

  // 模块解析规则
  resolve: {
    modules: ['node_modules', path.resolve(__dirname, 'app')], // 模块查找目录
    extensions: ['.js', '.json', '.jsx', '.css'], // 无后缀匹配列表
    alias: {
      'module': 'new-module', // 模块别名
      'only-module$': 'new-module', // 精准匹配别名
    },
    symlinks: true, // 跟随软链接
    descriptionFiles: ['package.json'], // 描述文件
    mainFields: ['main'], // 入口字段优先级
    enforceExtension: false, // 不强制导入带后缀
  },

  // 性能检查
  performance: {
    hints: 'warning', // 性能问题输出警告
    maxAssetSize: 200000, // 最大文件大小(字节)
    maxEntrypointSize: 400000, // 最大入口文件大小(字节)
    assetFilter: function(assetFilename) {
      return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
    },
  },

  devtool: 'source-map', // Source Map类型
  context: __dirname, // 根目录(绝对路径)
  target: 'web', // 运行环境
};

模块小结:整体配置结构梳理了所有核心配置项的层级与数据类型,是搭建完整Webpack配置文件的参考蓝本,可根据项目需求按需裁剪、扩展。

【本篇核心知识点速记】

  1. 配置方式:支持文件(webpack.config.js)与命令行参数两种方式,可搭配使用;配置项按功能分为Entry、Output等8大核心类别。
  2. Entry:context为绝对路径,决定相对路径解析根目录;支持string/array/object静态配置,及同步/异步函数动态配置;Chunk名称由Entry类型决定(string/array为main,object为键名)。
  3. Output:filename支持[name]/[id]/[hash]/[chunkhash]变量,chunkhash针对运行时Chunk;path为本地输出目录(绝对路径),publicPath为线上资源URL前缀;libraryTarget/library适配库开发的导出规则。
  4. Module:Loader通过test/include/exclude匹配文件,执行顺序默认从右到左(enforce调整);noParse忽略非模块化文件解析,parser精细控制模块化语法。
  5. Resolve:alias简化导入路径($精准匹配),mainFields调整第三方模块入口优先级,modules扩展模块查找目录,extensions定义无后缀匹配规则。
  6. DevServer:hot开启热替换,historyApiFallback适配单页路由,host设为0.0.0.0允许局域网访问,https可配置自定义证书。
  7. 其他配置:target适配运行环境,devtool控制Source Map生成,externals忽略外部模块打包,watchOptions优化文件监听性能。