webpack基本使用

470 阅读10分钟

webpack 是一个现代 javascript 应用程序的静态模块打包器(module bundler),当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle(包) 在这里插入图片描述

webpack基本使用

webpack四个核心概念:

  • 入口(entry):告诉 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始,默认值为 ./src
  • 输出(output):告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist
  • loader:可以将所有类型的文件转换为 webpack 能够处理的有效模块,让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)
  • 插件(plugins):用于扩展 webpack 的功能,相比于 loader, 插件功能更为强大,范围包括从打包优化和压缩,一直到重新定义环境中的变量,可以用于执行范围更广的任务

webpack打包的基本配置

新建项目目录:输出目录 /dist(打包后存放目录),/src(源代码目录)下面创建入口文件 main.js 初始化项目:

npm init

执行初始化项目会生成 pakeage.json 文件,这个文件主要用于记录在项目开发中所要用到的包,以及项目的详细信息等记录 安装 webpack webpack-cli

npm install webpack webpack-cli -D

package.json 文件中配置 scripts:

{
	......
	"scripts": {
		//执行打包:npm run build
		"build": "webpack --config webpack.config.js"
	}
}

新建 webpack 的配置文件 webpack.config.js

const path = require('path');
//导出配置对象
module.exports = {
    //entry:入口文件配置(从哪个文件开始打包)
    entry: './src/main.js',
    //output:出口文件配置(打包到哪里)
    output: {
        //打包输出的目录(绝对路径)
        //path.resolve()方法会把一个路径或路径片段的序列解析为一个绝对路径
        //__dirname是nodejs的一个全局变量,指向被执行js文件的绝对路径
        path: path.resolve(__dirname, 'dist'),
        //打包后生成的文件名
        filename: 'js/bundle.js'
    },
    //mode:打包模式:production(压缩),development(不压缩)
    mode: 'development'
}

执行配置的 scripts 脚本进行打包:

npm run build

执行打包后 /dist/js 文件夹下会有打包后的 bundle.js 文件

自动生成html插件:html-webpack-plugin

html-webpack-plugin 插件简化了HTML文件的创建实现,将为你生成一个 HTML5 文件, 其中包括使用 script 标签的 body 中的所有 webpack 包,实现 public 目录下 index.html 不需要手动引入打包后的文件,会被该插件自动生成 HTML 文件引入

安装 html-webpack-plugin:

npm install html-webpack-plugin -D

配置 webpack.config.js :

//引入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
//导出配置对象
module.exports = {
	......
	//plugins:插件配置
    plugins: [
    	......
        new HtmlWebpackPlugin({ 
        	//html模板文件路径
        	templte: './public/index.html' 
        })
    ]
}

执行打包后 /dist 文件夹下会有 index.html 文件,并已经引入了打包后的文件

webpack使用Babel降级处理高版本的js语法

Babel 是 JavaScript 编译器,主要用于在旧的浏览器或环境中将 ECMAScript 2015+ 代码转换为向后兼容的版本 babel-loader:允许你使用 Babel 和 webpack 转译 JavaScript 文件 安装依赖:

npm install -D babel-loader @babel/core @babel/preset-env

配置 webpack.config.js :

//导出配置对象
module.exports = {
	......
    //module:模块加载规则
    module: {
        ......
        //loader:加载器的规则
        rules: [
            ......
            {   
                //test:标识出被loader进行转换的文件
                //正则表达式,匹配所有js文件
                test: /\.js$/,
                //排除文件(排除node_modules文件夹)
                exclude: /(node_modules)/,
                //use:配置转换时使用的loader
                //处理顺序:从右向左执行
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    }
}

webpack打包前清除dist目录

clean-webpack-plugin 插件可以在每次打包前清除 dist 文件夹,再打包生成新的打包文件 安装 clean-webpack-plugin:

npm install clean-webpack-plugin -D

配置 webpack.config.js :

//引入clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
//导出配置对象
module.exports = {
    ......
    //plugins:插件配置
    plugins: [
        ......
        new CleanWebpackPlugin()
    ]
}

loader使用

webpack 可以使用 loader 来预处理文件,webpack 只能理解 JavaScript 和 JSON 文件,loader 让 webpack 能够处理其他类型的文件,并将它们转换为有效模块,这允许你打包除 JavaScript 之外的任何静态资源

webpack处理css文件

style-loader :将模块的导出作为样式添加到 DOM 中 css-loader :解析 CSS 文件后,使用 import 加载,并且返回 CSS 代码 入口文件 main.js 中使用 require() 引入css文件 安装 style-loader 和 css-loader:

npm install style-loader css-loader -D

配置 webpack.config.js :

//导出配置对象
module.exports = {
	......
    //module:模块加载规则
    module: {
    	......
        //loader:加载器的规则
        rules: [
        	......
            {
                //test:标识出被loader进行转换的文件
                //正则表达式,匹配所有css文件
                test: /\.css$/,
                //use:配置转换时使用的loader
                //处理顺序:从右向左执行
                //css-loader:让webpack能够识别解析css文件
                //style-loader:通过js动态创建style标签,让解析后的css作用到页面中
                use: ['style-loader', 'css-loader']
            }
        ]
    }
}

执行打包后,css文件会被打包到 bundle.js 中

分离css文件插件:mini-css-extract-plugin

mini-css-extract-plugin 插件可以将 CSS 提取为独立的文件,对每个包含 css 的 js 文件都会创建一个CSS文件,支持按需加载 css 和 sourceMap,该插件只能用于 webpack4 中 安装 mini-css-extract-plugin:

npm install mini-css-extract-plugin -D

配置 webpack.config.js :

//引入mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
//导出配置对象
module.exports = {
    ......
    //module:模块加载规则
    module: {
        //loader:加载器的规则
        rules: [
        	......
            {
                //test:标识出被loader进行转换的文件
                //正则表达式,匹配所有css文件
                test: /\.css$/,
                //use:配置转换时使用的loader
                //处理顺序:从右向左执行
                //css-loader:让webpack能够识别解析css文件
                //mini-css-extract-plugin:分离css文件
                use: [
	                {
	                    loader: MiniCssExtractPlugin.loader,
	                    options: {
	                        //公共资源加载路径
	                        publicPath: '../'
	                    }
	                }, 
	                'css-loader'
	            ]
            }
        ]
    },
    //plugins:插件配置
    plugins: [
        ......
        new MiniCssExtractPlugin({
            //打包好文件的存放路径和文件名(/dist/css/index.css)
            filename: 'css/index.css'
        })
    ]
}

执行打包后 /dist/css 文件夹下会有打包后的 index.css 文件

webpack处理less文件

less-loader:加载和转译 LESS 文件 入口文件 main.js 中使用 require() 引入less文件 安装 less 和 less-loader:

npm install less less-loader -D

配置 webpack.config.js :

//导出配置对象
module.exports = {
	......
    //module:模块加载规则
    module: {
        ......
        //loader:加载器的规则
        rules: [
            ......
            {
                //test:标识出被loader进行转换的文件
                //正则表达式,匹配所有less文件
                test: /\.less$/,
                //use:配置转换时使用的loader
                //处理顺序:从右向左执行
                //less-loader:将less文件转换成css文件
                //css-loader:让webpack能够识别解析css文件
                //mini-css-extract-plugin:分离css文件
                use: [
                    {
	                    loader: MiniCssExtractPlugin.loader,
	                    options: {
	                        //公共资源加载路径
	                        publicPath: '../'
	                    }
	                },  
                    'css-loader', 
                    'less-loader'
                ]
            }
        ]
    }
}

webpack处理图片

file-loader: 将文件发送到输出文件夹,并返回(相对)URL url-loader: 像 file loader 一样工作,但如果文件小于限制,可以返回 data URL 安装 url-loader 和 file-loader:

npm install url-loader file-loader -D

配置 webpack.config.js :

//导出配置对象
module.exports = {
	......
    //module:模块加载规则
    module: {
        ......
        //loader:加载器的规则
        rules: [
            ......
            {
                //test:标识出被loader进行转换的文件
                //正则表达式,匹配所有以.png .jpg .gif结尾的文件
                test: /\.(png|jpg|gif)$/i,
                //use:配置转换时使用的loader
                //处理顺序:从右向左执行
                //url-loader:让webpack能够识别解析图片文件
                //图片会默认转成base64字符串,如果图片太大再转base64会让图片体积增大,可以通过options配置limit限制图片的转换
                //图片打包后默认直接输出到dist目录下,可以通过options配置输出到指定目录下
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            //图片小于8k,转换成base64,节约请求次数,大于8k,不转换成base64
                            limit: 8 * 1024,
                            //输出文件名
                            name: '[name].[ext]',
                            //静态资源引用路径
                            publicPath: '../images/',
                            //输出的文件目录
                            outputPath: 'images/'
                        }
                    }
                ]
            }
        ]
    }
}

webpack处理vue文件

安装 vue:

npm install vue

vue-loader:加载和转译 Vue 组件 vue-template-compiler:,模板解析器,解析 Vue 模板预编译为渲染函数 安装 vue-loader 和 vue-template-compiler:

npm install vue-loader vue-template-compiler -D

配置 webpack.config.js :

//引入vue-loader
const VueLoaderPlugin = require('vue-loader/lib/plugin')
//导出配置对象
module.exports = {
	......
    //module:模块加载规则
    module: {
    	......
        //loader:加载器的规则
        rules: [
        	......
            {
            	//test:标识出被loader进行转换的文件
                //正则表达式,匹配所有vue文件
		        test: /\.vue$/,
		        loader: 'vue-loader'
		    }
        ]
    },
    //plugins:插件配置
    plugins: [
        ......
        new VueLoaderPlugin()
    ]
}

创建vue根组件 App.vue:

<template>
  <div id="app"></div>
</template>

<script>
export default {

}
</script>

<style>

</style>

编写入口文件 main.js:

//引入vue
import Vue from 'vue'
//引入根组件App.vue
import App from './App.vue'
//创建vue实例
new Vue({
	//提供一个页面上已存在的DOM元素作为vue实例的挂载目标
    el: '#app',
    //render函数用于渲染一个组件作为根组件(固定写法)
    render (createElement) {
        //把App.vue组件渲染为根组件
        return createElement(App)
    }
})

vue-cli脚手架环境下的webpack配置

在项目根目录下创建vue配置文件 vue.config.js,在 vue.congfig.js 中进行 webpack 配置,会覆盖 vue-cli 中 webpack 的默认配置 vue.congfig.js:

//导出配置对象
module.exports = {
	......
}

webpack开发服务器

在项目开发的过程中,可以使用 webpack 启动一个开发服务器,方便实时查看调试项目

自动刷新服务器插件:webpack-dev-server

webpack-dev-server 为你提供了一个具有 live reloading(实时重新加载) 功能的简单的 web server,并且可以实现反向代理,解决在开发过程中的跨域问题 安装 webpack-dev-server:

npm install webpack-dev-server -D

配置 package.json:

{
    ......
    "scripts": {
        //执行打包:npm run build
        "build": "webpack --config webpack.config.js",
        //执行启动服务器:npm run dev
	    "dev": "webpack-dev-server --config webpack.config.js"
    }
}

配置 webpack.config.js :

//导出配置对象
module.exports = {
	......
    //devServer:开发服务器配置
    devServer: {
        //端口号
        port: 9999, 
        //自动打开浏览器
  	    open: true
    }
}

执行配置的 scripts 脚本启动开发服务器:

npm run dev

反向代理配置:

通过开发服务器配置实现反向代理,解决在开发过程中的跨域问题 配置 webpack.config.js :

//导出配置对象
module.exports = {
	......
    //devServer:开发服务器配置
    devServer: {
        //端口号
        port: 9999, 
        //自动打开浏览器
  	    open: true,
  	    //反向代理配置
  	    proxy: {
  	    	//只要以/api接口开头的请求都会被反向代理
  	    	//需要修改请求地址中的'https://blog.csdn.net/weixin_45426836'为'/api'
  	    	//结果为:/api/a => https://blog.csdn.net/weixin_45426836/a
			'/api': {
				//反向代理基础路径
				target: 'https://blog.csdn.net/weixin_45426836',
				//路径重写(把/api从路径中去掉)
				pathRewrite: { '^/api': '' }
			}
		}
    }
}

上面反向代理配置情况下需要在请求接口时将地址中的 'blog.csdn.net/weixin_4542…' 改成 '/api'

webpack多入口多输出配置

在项目中如果需要引入多个入口文件,例如/src(源代码目录)下面有两个入口文件 one.jstwo.js,两个入口文件独立存在,没有引用关系 配置 webpack.config.js:

const path = require('path');
//导出配置对象
module.exports = {
    //entry:入口文件配置(从哪个文件开始打包)
    //用对象的方式配置多个入口
    entry: {
		one: './src/one.js',
		two: './src/two.js'
	},
    //output:出口文件配置(打包到哪里)
    output: {
        //打包输出的目录(绝对路径)
        path: path.resolve(__dirname, 'dist'),
        //打包后生成的文件名
        //[name]动态读取entry的属性(one,two)
        filename: 'js/[name].bundle.js'
    }
}

执行打包后 /dist/js 文件夹下会有 one.bundle.js 和 two.bundle.js 两个打包后的文件

提取公共模块

在项目中如果引入多个文件,这些文件中如果有相同的模块(例如:都引入了jQuery库),就会被重复打包,为了避免这些模块被重复打包,减小打包后文件的体积,需要把公共模块提取到单独的文件中 配置 webpack.config.js

//导出配置对象
module.exports = {
    ......
    //optimization:优化配置
    optimization: {
        //代码块分割配置
        splitChunks: {
            //分割所有代码块
            chunks: 'all',
            //代码块分割后的名称,true表示基于块和缓存组密钥自动生成一个名称
            name: true
        }
    }
}

公共模块的大小必须大于30kb才会被打包到独立的文件中 执行打包后 /dist/js 文件夹下会有提取公共模块的文件

分离 开发环境(development)和 生产环境(production)的配置文件

开发环境(development)用于开发过程中的本地运行,而 生产环境(production)用于运行在线上服务器,为了打包后运行在线上服务器的打包文件尽可能小,需要对开发环境和生产环境的 webpack 配置文件进行拆分,并抽离出公共配置部分 使用 webpack-merge 对开发环境 / 生产环境与公共的 webpack 配置文件进行合并 安装 webpack-merge:

npm install webpack-merge -D

新建 /config 文件夹用于存放拆分的 webpack 配置文件:

  • /config
    • webpack.common.js ------ 公共配置文件
    • webpack.dev.js ------ 开发环境配置文件
    • webpack.pro.js ------ 生产环境配置文件
公共配置文件 webpack.common.js:
const path = require('path');
//引入自动生成html插件:html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
//引入分离css文件插件:mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
//引入清除dist文件夹插件:clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

//导出配置对象
module.exports = {
    //entry:入口文件配置(从哪个文件开始打包)
    entry: './src/main.js',
    //output:出口文件配置(打包到哪里)
    output: {
        //打包输出的目录(绝对路径)
        path: path.resolve(__dirname, 'dist'),
        //打包后生成的文件名
        filename: 'js/bundle.js'
    },
  	//module:模块加载规则
    module: {
        rules: [
            //处理css文件
            {
                //test:标识出被loader进行转换的文件
                //正则表达式,匹配所有css文件
                test: /\.css$/,
                //use:配置转换时使用的loader
                //处理顺序:从右向左执行
                //css-loader:让webpack能够识别解析css文件
                //mini-css-extract-plugin:分离css文件
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader,
                        options: {
                            //公共资源加载路径
                            publicPath: '../'
                        }
                    }, 
                    'css-loader'
                ]
            },
            //处理less文件
            {
                //test:标识出被loader进行转换的文件
                //正则表达式,匹配所有less文件
                test: /\.less$/,
                //use:配置转换时使用的loader
                //处理顺序:从右向左执行
                //less-loader:将less文件转换成css文件
                //css-loader:让webpack能够识别解析css文件
                //mini-css-extract-plugin:分离css文件
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader,
                        options: {
                            //公共资源加载路径
                            publicPath: '../'
                        }
                    },  
                    'css-loader', 
                    'less-loader'
                ]
            },
            //处理图片
            {
                //test:标识出被loader进行转换的文件
                //正则表达式,匹配所有以.png .jpg .gif结尾的文件
                test: /\.(png|jpg|gif)$/i,
                //use:配置转换时使用的loader
                //处理顺序:从右向左执行
                //url-loader:让webpack能够识别解析图片文件
                //图片会默认转成base64字符串,如果图片太大再转base64会让图片体积增大,可以通过options配置limit限制图片的转换
                //图片打包后默认直接输出到dist目录下,可以通过options配置输出到指定目录下
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            //图片小于8k,转换成base64,节约请求次数,大于8k,不转换成base64
                            limit: 8 * 1024,
                            //输出文件名
                            name: '[name].[ext]',
                            //静态资源引用路径
                            publicPath: '../images/',
                            //输出的文件目录
                            outputPath: 'images/'
                        }
                    }
                ]
            },
            //使用Babel降级处理高版本的js语法
            {   
                //test:标识出被loader进行转换的文件
                //正则表达式,匹配所有js文件
                test: /\.js$/,
                //排除文件(排除node_modules文件夹)
                exclude: /(node_modules)/,
                //use:配置转换时使用的loader
                //处理顺序:从右向左执行
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    },
    //plugins:插件配置
    plugins: [
        //自动生成html插件:html-webpack-plugin
        new HtmlWebpackPlugin({ 
        	//html模板文件路径
        	templte: './public/index.html' 
        }),
        //分离css文件插件:mini-css-extract-plugin
        new MiniCssExtractPlugin({ 
            //打包好文件的存放路径和文件名(/dist/css/index.css)
            filename: 'css/index.css'
        }),
        //清除dist文件夹插件:clean-webpack-plugin
        new CleanWebpackPlugin()
    ]
}
开发环境配置文件 webpack.dev.js:
//引入公共配置文件:webpack.common.js
const common = require('./webpack.common.js')
//引入合并配置文件的插件:webpack-merge
const merge = require('webpack-merge')
//webpack-merge可以接受多个参数, 会把参数对象合并成一个对象,如果有重复,后面的对象属性, 会覆盖前面的对象属性
//导出配置对象
module.exports = merge(common, {
    //devServer:开发服务器配置
    devServer: {
        //端口号
        port: 9999, 
        //自动打开浏览器
  	    open: true
    },
    //mode:打包模式:开发环境
    mode: 'development'
})
生产环境配置文件配置文件 webpack.pro.js:
//引入公共配置文件:webpack.common.js
const common = require('./webpack.common.js')
//引入合并配置文件的插件:webpack-merge
const merge = require('webpack-merge')
//webpack-merge可以接受多个参数, 会把参数对象合并成一个对象,如果有重复,后面的对象属性, 会覆盖前面的对象属性
//导出配置对象
module.exports = merge(common, {
    //mode:打包模式:生产环境
    mode: 'production'
})

对开发环境和生产环境的 webpack 配置文件进行拆分后,可以删除 webpack.config.js 配置 package.json,修改配置文件路径:

{
    ......
    "scripts": {
        //执行打包:npm run build
        //修改打包文件路径为 config/webpack.pro.js(打包生产环境的配置文件)
        "build": "webpack --config config/webpack.pro.js",
        //执行启动服务器:npm run dev(启动开发服务器执行开发环境的配置文件)
        //修改服务器启动文件路径为 config/webpack.dev.js
	    "dev": "webpack-dev-server --config config/webpack.dev.js"
    }
}

参考文档

webpack中文文档:www.webpackjs.com/concepts/