概念
来看一下官网对webpack的定义:
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle。
首先webpack是一个静态模块打包器,所谓的静态模块,包括脚本、样式表和图片等等;webpack打包时首先遍历所有的静态资源,根据资源的引用,构建出一个依赖关系图,然后再将模块划分,打包出一个或多个bundle。再次白piao一下官网的图,生动的描述了这个过程:
提到webpack,就不得不提webpack的四个核心概念
- 入口(entry):指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始
- 输出(output):在哪里输出它所创建的 bundles
- loader:让 webpack 能够去处理那些非 JavaScript 文件
- 插件(plugins):用于执行范围更广的任务
你的第一个打包器
我们首先在全局安装webpack:
npm install webpack webpack-cli –g
webpack可以不使用配置文件,直接通过命令行构建,用法如下:
webpack <entry> [<entry>] -o <output>
这里的entry和output就对应了上述概念中的入口和输入,我们来新建一个入口文件:
//demo1/index.js
var a = 1
console.log(a)
document.write('hello webpack')
有了入口文件我们还需要通过命令行定义一下输入路径dist/bundle.js:
webpack index.js -o dist/bundle.js
这样webpack就会在dist目录生成打包后的文件。
我们也可以在项目目录新建一个html引入打包后的bundle.js文件查看效果。
配置文件
命令行的打包方式仅限于简单的项目,如果我们的项目较为复杂,有多个入口,我们不可能每次打包都把入口记下来;因此一般项目中都使用配置文件来进行打包;配置文件的命令方式如下:
webpack [--config webpack.config.js]
配置文件默认的名称就是webpack.config.js
,一个项目中经常会有多套配置文件,我们可以针对不同环境配置不同的文件,通过--config
来进行切换:
//生产环境配置
webpack --config webpack.prod.config.js
//开发环境配置
webpack --config webpack.dev.config.js
相关webpack视频讲解:进入学习
多种配置类型
config配置文件通过module.exports
导出一个配置对象:
//webpack.config.js
var path = require('path');
module.exports = {
mode: 'development',
//入口文件
entry: './index.js',
//输出目录
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
除了导出为对象,还可以导出为一个函数,函数中会带入命令行中传入的环境变量等参数,这样可以更方便的对环境变量进行配置;比如我们在打包线上正式环境和线上开发环境可以通过env
进行区分:
var path = require('path');
//env:环境对象
module.exports = function(env, argv){
return {
//其他配置
entry: './index.js',
output: {
}
}
};
另外还可以导出为一个Promise,用于异步加载配置,比如可以动态加载入口文件:
module.exports = () => {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve({
entry: './index.js',
output: {
}
})
}, 5000)
})
}
入口
正如在上面提到的,入口是整个依赖关系的起点入口;我们常用的单入口配置是一个页面的入口:
module.exports = {
entry: './index.js',
}
它是下面的简写:
module.exports = {
entry: {
main: './index.js'
},
}
但是我们一个页面可能不止一个模块,因此需要将多个依赖文件一起注入,这时就需要用到数组了,代码在demo2中:
module.exports = {
entry: [
//轮播图模块
'./src/banner.js',
//主模块
'./src/index.js',
//底部模块
'./src/foot.js'
],
}
有时候我们一个项目可能有不止一个页面,需要将多个页面分开打包,entry支持传入对象的形式,代码在demo3中:
//demo3
module.exports = {
entry: {
home: './src/home.js',
list: './src/list.js',
detail: ['./src/detail.js', './src/common.js'],
},
}
这样webpack就会构建三个不同的依赖关系。
输出
output
选项用来控制webpack如何输入编译后的文件模块;虽然可以有多个entry,但是只能配置一个output
:
module.exports = {
entry: './src/index.js', output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
//CDN地址
publicPath: '/',
},
}
这里我们配置了一个单入口,输出也就是bundle.js;但是如果存在多入口的模式就行不通了,webpack会提示Conflict: Multiple chunks emit assets to the same filename
,即多个文件资源有相同的文件名称;webpack提供了占位符
来确保每一个输出的文件都有唯一的名称:
module.exports = {
entry: {
home: './src/home.js',
list: './src/list.js',
detail: ['./src/detail.js', './src/common.js'],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js',
},
}
这样webpack打包出来的文件就会按照入口文件的名称来进行分别打包生成三个不同的bundle文件;还有以下不同的占位符字符串:
占位符 | 描述 |
---|---|
[hash] | 模块标识符(module identifier)的 hash |
[chunkhash] | chunk 内容的 hash |
[name] | 模块名称 |
[id] | 模块标识符 |
[query] | 模块的 query,例如,文件名 ? 后面的字符串 |