webpack常用配置详解

3,266 阅读3分钟

简介常用webpack配置

准备

知识储备

本文主要记录常用的配置,适对webpack有一些基础了解的同学,未了解webpack的可移步下方的官方文档的简介。

webpack四个核心概念

  • 入口(entry): 指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。
  • 输出(output): 告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。
  • loader: 让 webpack 能够去处理那些非 JavaScript 文件。
  • 插件(plugins): webpack提供很多钩子可以让开发者进行二次开发插件,完成很多丰富的功能。

本文也主要围绕这四个概念,介绍webpack常用的插件等的配置。

loader和plugin的区别

  • loader:由于webpack只能识别js,loader相当于翻译官的角色,帮助webpack对其他类型的资源进行转译的预处理工作。
  • plugins:plugins扩展了webpack的功能,在webpack运行时会广播很多事件,plugin可以监听这些事件,然后通过webpack提供的API来改变输出结果。

配置示例

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装

module.exports = {
    entry: './path/to/my/entry/file.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-first-webpack.bundle.js'
    },
    module: {
        rules: [
          { test: /\.txt$/, use: 'raw-loader' }
        ]
    },
    plugins: [
      	new HtmlWebpackPlugin({template: './src/index.html'})
    ]
};

一、开发工具

1. webpack-dev-server

webpack-dev-server会在本地开启一个服务,方便本地开发

安装依赖,配置好webpack.config.js后运行下面命令即可看到浏览器中打开的页面

webpack-dev-server --config webpack.config.js
  • 安装依赖:
npm i -D webpack webpack-dev-server html-webpack-plugin
  • 配置示例:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
module.exports = {
    mode: 'development',
    devServer: {
        port: 8080,
        hot: true,// 局部更新
        compress: true,//是否压缩
        open: true,// 自动打开浏览器
        contentBase: 'dist'
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html',
            filename: 'index.html',
        }),
        new webpack.HotModuleReplacementPlugin(),
    ]
}

2. mock模拟数据

如果本地开发时想使用mock模拟数据来响应页面中的ajax请求,那么就需要特殊配置一下,详情请见我的另一篇文章。

二、常用loader

1. css、less、sass相关配置

  • 安装依赖:
npm i -D style-loader css-loader less-loader
  • 配置示例:
module.exports = {
    module: {
        rules: [
            // 规则 css-loader主要解析我们样式中@import语法, 执行顺序是重右向左执行 - >重下到上
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    'style-loader', 
                    'css-loader',
                    'less-loader'
                ]
            }
        ]
    }
};

2. 自动为css3样式加上-webkit等浏览器兼容前缀

使用 postcss,需要使用 postcss-loader 和 autoprefixer

  • 安装依赖:
npm i -D postcss-loader autoprefixer
  • 配置示例:
[{
    test: /\.css$/,
    use: [
        'style-loader',
        'css-loader',
        'postcss-loader', // 给css3的样式加上-webkit等浏览器兼容前缀
    ]
},
{
    test: /\.less$/,
    use: [
        'style-loader', 
        'css-loader',
        'postcss-loader', // postcss-loader 放置在 css-loader 右边
        'less-loader'
    ]
},
{
    test: /\.scss/,
    use: [
    	'style-loader', 
        'css-loader',
        'postcss-loader',
        'sass-loader'
    ]
}]
  • 项目根目录下添加 postcss 的配置文件: postcss.config.js
module.exports = {
    plugins: [
        require('autoprefixer')({
            browsers: [
              // 加这个后可以出现额外的兼容性前缀
              "> 0.01%"
            ]
        })
    ]
}

3. 图片loader

file-loader和url-loader都是用来处理图片、字体图标等文件。

url-loader工作时分两种情况:

  1. 当文件大小小于limit参数,url-loader将文件转为base-64编码,用于减少http请求;
  2. 当文件大小大于limit参数时,调用file-loader进行处理;

因此我们优先使用url-loader,首先还是进行安装,安装url-loader之前还需要把file-loader先安装;

另外html上引用一个图片,为了使打包后的html不是引用了原目录下的图片,需要使用html-withimg-loader

  • 安装依赖:
npm i -D file-loader url-loader html-withimg-loader
  • 配置示例:
{
    //省略其他配置
    rules: [{
        test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
        use: {
            loader: 'url-loader',
            options: {
                //10k
                limit: 10240,
                //生成资源名称
                name: '[name].[hash:8].[ext]',
                //生成资源的路径
                outputPath: 'imgs/',
                esModule: false
            },
            exclude: /node_modules/,
        }
    },{
        test: /\.(htm|html)$/,
        use: {
            loader: 'html-withimg-loader'
        }
    }]
}

4. vue-loader

使用 vue-loader,注意加入VueLoaderPlugin以及

npm install -D vue-loader vue-template-compiler
  • 配置示例:
// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
    mode: 'development',
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            },
            // 它会应用到普通的 `.js` 文件
            // 以及 `.vue` 文件中的 `<script>` 块
            {
                test: /\.js$/,
                loader: 'babel-loader'
            },
            // 它会应用到普通的 `.css` 文件
            // 以及 `.vue` 文件中的 `<style>` 块
            {
                test: /\.css$/,
                use: [
                    'vue-style-loader',
                    'css-loader'
                ]
            }
        ]
	},
    plugins: [
        // 请确保引入这个插件来施展魔法
        new VueLoaderPlugin()
    ]
}

5. svg-loader

使用svg有以下四种方式:

  • 直接当作图片使用: 背景图片或img标签的src属性
  • raw-loader: 解析svg为文本,当作dom节点使用
  • svg-inline-loader: 压缩svg代码
  • svg-sprite-loader: 和vue一起使用

直接使用

css

body {
  	background-image: url(./svgs/activity.svg);
}

html

<img src="./svgs/activity.svg"/>

raw-loader

raw-loader 可以把文本文件的内容读取出来,注入到 JavaScript 或 css 中去。

由于 raw-loader 会直接返回 svg 的文本内容,并且无法通过 css 去展示 svg 的文本内容,因此采用本方法后无法在css中导入svg。

也就是说在 css 中不可以出现 background-image: url(./svgs/activity.svg) 这样的代码,因为 background-image: url(<svg>...</svg>) 是不合法的。

配置

module.exports = {
    module: {
        rules: [
            {
              test: /\.svg$/,
              use: ['raw-loader']
            }
        ]
    }
};

使用

import svgContent from './svgs/alert.svg';
window.document.getElementById('svg').innerHTML = svgContent;

svg-inline-loader

svg-inline-loader 和上面提到的 raw-loader 非常相似, 不同在于 svg-inline-loader 会分析 SVG 的内容,去除其中不必要的部分代码,以减少 SVG 的文件大小。

配置

module.exports = {
    module: {
        rules: [
            {
              test: /\.svg$/,
              use: ['svg-inline-loader']
            }
        ]
    }
};

svg-sprite-loader + vue

好处:

  • 推荐在vue脚手架中使用
  • 页面代码清爽
  • 可使用 ID 随处重复调用
  • 每个 SVG 图标都可以更改大小颜色

使用

  • 安装依赖:
npm i -D svg-sprite-loader
  • 配置示例:
module.exports = {
    module: {
        rules: [
            {
                test: /\.svg$/,
                loader: 'svg-sprite-loader',
                include: [resolve('src/icons')],
                options: {symbolId: 'icon-[name]'}
            },
            {
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                loader: "url-loader",
                // 排除字体图标文件
                exclude: [path.resolve(__dirname, '../src/icons/svg')],
                options: {
                    limit: 10000,
                    name: utils.assetsPath("img/[name].[hash:7].[ext]")
                }
            }
        ]
    }
};

创建svg文件目录/src/icons/svg 里面呢放置所有svg文件,还有/src/icons/index.js.
/src/icons/index.js

import Vue from 'vue';
import VIcon from '@/components/VIcon'; // svg组件
Vue.component('v-icon', VIcon); // 全局注册
const requireAll = requireContext => requireContext.keys().map(requireContext);
const req = require.context('./svg', false, /\.svg$/);
requireAll(req);

新建VIcon.vue组件

<template>
    <svg :class="svgClass" aria-hidden="true">
      <use :xlink:href="iconName"></use>
    </svg>
</template>

<script>
export default {
    name: 'v-icon',
    props: {
        name: {
            type: String,
            required: true
        },
        className: {
          	type: String
        }
    },
    computed: {
        iconName() {
          	return `#icon-${this.name}`
        },
        svgClass() {
            if (this.className) {
              	return 'svg-icon ' + this.className
            } else {
              	return 'svg-icon'
            }
        }
    }
}
</script>

<style scoped>
.svg-icon {
    width: 1em;
    height: 1em;
    vertical-align: -0.15em;
    fill: currentColor;
    overflow: hidden;
}
</style>

在main.js中引入

import './icons/index.js'

这样就能在vue中使用了 具体格式如下

<v-icon name="svg文件名"/>

三、常用插件(Plugin)

webpack提供很多钩子可以让开发者进行二次开发插件,完成很多丰富的功能。plugins扩展了webpack的功能,在webpack运行时会广播很多事件,plugin可以监听这些事件,然后通过webpack提供的API来改变输出结果。

1. html-webpack-plugin

详情见下面的文章

2. clean-webpack-plugin

clean-webpack-plugin用于在打包前清理上一次项目生成的bundle文件,它会根据output.path自动清理文件夹;这个插件在生产环境用的频率非常高,因为生产环境经常会通过hash生成很多bundle文件,如果不进行清理的话每次都会生成新的,导致文件夹非常庞大;

  • 安装依赖:
npm i -D clean-webpack-plugin
  • 配置示例:
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
    //其他配置
    plugins: [
        new CleanWebpackPlugin()
    ]
}

3. mini-css-extract-plugin

mini-css-extract-plugin就可以帮我从js中单独抽离css样式文件。通常开发环境使用style-loader,生产环境使用mini-css-extract-plugin。

  • 安装依赖:
npm i -D mini-css-extract-plugin
  • 配置示例:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
    //其他配置
    module: {
        rules: [
            {
                test: /\.less/,
                use: [{
                    loader: isDev ? 'style-loader' : MiniCssExtractPlugin.loader
                },{
                    loader: 'css-loader'
                },{
                    loader: 'less-loader'
                }]
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: "[name].[hash:8].css",
        })
    ]
}

4. optimize-css-assets-webpack-plugin

用于生产环境,对css进行压缩

  • 安装依赖:
npm i optimize-css-assets-webpack-plugin -D
  • 配置示例:
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
    // 其他配置
    plugins: [
        new OptimizeCSSAssetsPlugin(),
    ]
}

5. copy-webpack-plugin

打包的时候,将静态资源拷贝到dist目录

  • 安装依赖:
npm i -D copy-webpack-plugin
  • 配置示例:
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
    plugins: [
        new CopyWebpackPlugin({
            patterns: [
                {
                    from: 'static/js/*.js',
                    to: path.resolve(__dirname, 'dist', 'js'),
                    flatten: true,
                }
            ]
        }),
    ]
}

四、扩展

五、参考

本文严重参考以下文章: