# webpack配置详解

# entry

entry: 入口起点
	1. string(单入口)  --> entry: './src/index.js',
		打包形成一个chunk,输出一个bundle文件
		此时chunk的默认名称为main
	2. array(多入口)  --> entry: ['./src/index.js','./src/add.js'],
		所有入口文件最终只会形成一个chunk,输出一个bundle文件
		只有在HMR功能中让html热更新生效~
	3. object(多入口)
		entry: {
			index: './src/index.js',
			add: './src/add.js'
		},
		有几个入口文件就形成几个chunk,输出几个bundle文件,此时chunk的名称就是key
	4. 特殊用法
		{
			// 所有入口文件最终会形成一个chunk,输出出去只有一个bundle文件
			index: ['./src/index.js','./src/count.js']
			// 形成一个chunk,输出一个bundle文件
			add: './src/add.js'
		}

# output

output: {
    // 文件名称 (指定名称和目录)
    filename: '[name].js',
    // 输出文件目录(将来所有资源输出的公共目录)
    path: resolve(__dirname, 'build'),
    // 所有资源引入的公共路径前缀
    publicPath: "/",
    // 非入口chunk的名称
    chunkFilename: "[name]_chunk.js",
    library: '[name]', // 整个库向外暴露的变量名
    // libraryTarget: "window" // 变量名添加到哪个上 browser
    libraryTarget: "global" // 变量名添加到哪个上 browser
}

# module

module: {
    rules: [
        //loader的配置
        {
            test: /\.css$/,
            // 多个loader用use
            use: ['style-loader','css-loader']
        },
        {
            test: /\.js$/,
            // 排除node_modules
            exclude: '/node_modules',
            // 只检查src下面的js文件
            include: resolve(__dirname,'src'),
            enforce: "pre", // 优先执行
            // enforce: "post", 延后执行, 不写就是中间执行
            // 多个loader用loader
            loader: 'eslint-loader',
            options: {}
        },
        {
            // 以下配置只会生效一个
            oneOf: []
        }
    ]
}

# resolve

// 解析模块规则
resolve: {
    // 配置解析模块路径别名: 优点简写路径,缺点路径没有提示
    alias: {
        $css: resolve(__dirname,'src/css')
    },
    // 配置省略文件路径的后缀名
    extensions: ['.js','.json','.jsx'],
    // 告诉webpack 解析模块是去找哪个目录
    modules: [resolve(__dirname,'../../node_modules'),'node_modules']
}

# devServer

	devServer: {
        // 运行代码的目录
        contentBase: resolve(__dirname,'build'),
        // 监视 contentBase 目录下的所有文件, 一旦文件变化就会reload
        watchContentBase: true,
        watchOptions: {
            // 忽略文件
            ignored: 'node_modules'
        },
        // 启动gzip压缩
        compress: true,
        // 端口号
        host: 'localhost',
        // 自动打开浏览器
        open: true,
        // 开启HMR功能
        hot: true,
        // 不要显示启动服务器日志信息
        clientLogLevel: 'none',
        // 除了一些基本的启动信息以外,其他内容都不要打印
        quiet: true,
        // 如果出现错误,不要全屏显示
        overlay: false,
        // 服务器代理 解决开发环境跨域问题
        proxy: {
            // 一旦devServer(8080)服务器接收到/api/的请求,就会把请求转发到另一个服务器上(3000)
            '/api': {
                target: 'http://localhost:3000',
                // 发送请求时,请求路径重写: 将 /api/xxx --> /xxx(去掉/api)
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    }

# optimization

optimization: {
    splitChunks: {
        chunks: "all",
        minSize: 30 * 1024, // 分割的chunk最小为30kb
        maxSize: 0, // 最大没有限制
        minChunks: 1, // 要提取的chunk最少被引用1次
        maxAsyncRequests: 5, // 按需加载时并行加载的文件的最大数量
        maxInitialRequests: 3, // 入口js文件最大并行请求数量
        automaticNameDelimiter: "~", // 名称连接符
        name: true, // 可以使用命名规则
        // 分割chunk的组
        cacheGroups: {
            // node_modules的文件会被打包到 verdors组的 chunk中 --> verdors~xxx.js
            vendors: {
                test: /[\\]node_modules[\\/]/,
                // 打包优先级
                priority: -10,
            },
            default: {
                // 要提取的chunk最少被引用2次
                minChunks: 2,
                priority: -20,
                // 如果当前要打包的模块,和之前已经被提取的模块是同一个,就会复用,而不是重新打包模块
                reuseExistingChunk: true
            }
        }
    },
    // 将当前模块的记录其他模块的hash单独打包为一个文件 runtime
    // 解决:修改a文件导致b文件的contenthash的变化
    runtimeChunk: {
        name: entrypoint => `runtime-${entrypoint.name}`
    },
    minimizer: [
        // 配置生产环境的压缩方案:js 和 css
        new TerserWebpackPlugin({
            // 开启缓存
            cache: true,
            // 开启多进程打包
            parallel: true,
            // 启动source-map
            sourceMap: true
        })
    ]
},