初始化项目
新建项目的目录,并将命令行切换到该目录下:
mkdir webpackdemo && cd webpackdemo
初始化项目(我们自己开发的npm包,)
npm init -y
将package.json文件中的main字段替换成private字段,以便确保我们的项目是私有的
{
...
-"main": "index.js",
+"private": true,
...
}
安装webpack
webpack提供了2个软件包,在使用之前我们需要安装它们:
- webpack-cli,提供一些与webpack交互的命令
- webpack,提供了一些常用API,以及配置选项
本地安装webpack和webpack-cli,并作为项目的开发依赖。
npm install webpack webpack-cli --save-dev
不推荐全局安装 webpack。这样的话,你的项目所依赖的webpack 就被锁定到了指定版本,而且在使用不同的 webpack 版本的项目中,可能会导致构建失败。
使用webpack
由于webpack-cli是本地安装的,因此想要运行webpack命令,则需要将命令行切换到node_modules/.bin目录下,然后才能执行webpack命令。
Node 8.2/npm 5.2.0 以上版本提供的 npx 命令,可以运行在开始安装的 webpack package 中的 webpack 二进制文件(即 ./node_modules/.bin/webpack):
执行 npx webpack,会将我们的脚本 src/index.js 作为 入口起点,也会生成 dist/main.js 作为 输出。
在没有配置文件的情况下,执行webpack-cli命令时,webpack-cli会将src/index.js作为入口。
使用配置文件
在webpack v4中,无需任何配置,即可使用webpack,然而大多数项目往往需要很复杂的设置,这就是为什么 webpack 仍然要支持配置文件的原因。这比在命令行中手动输入大量命令要高效的多,所以让我们创建一个配置文件:
创建webpack配置文件webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
}
};
现在,让我们通过新的配置文件再次执行构建:
npx webpack --config webpack.config.js
比起直接在命令行输入参数的使用方式,配置文件具有更多的灵活性。我们可以通过配置方式指定 loader 规则(loader rule)、插件(plugin)、resolve 选项,以及许多其他增强功能。
注意事项:如果 webpack.config.js 存在,则 webpack 命令将默认选择使用它。我们在这里使用 --config 选项只是向你表明,可以传递任何名称的配置文件。这对于需要拆分成多个文件的复杂配置是非常有用。
使用npm scripts
考虑到用上面这种方式来运行本地的 webpack并不是特别方便,我们可以设置一个快捷方式。在package.json文件中配置npm命令:
{
其他字段...
"scripts": {
"build": "webpack --config webpack.config.js"
},
其他字段...
}
在webpack.config.js文件中导出一个对象,通过对象中的属性对webpack进行配置:
const path = require('path');
module.exports = {
mode: 'development', // 打包模式,目前配置的是开发模式
entry: './src/index.js', // 入口文件
output: { // 输出文件的配置
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
}
}
使用loader
由于webpack原始只支持JavaScript的打包,不支持其他文件类型的打包,因此不同类型的文件我们不同的loader来处理它们。
使用css-loader和style-loader处理css文件:
npm install css-loader style-loader –save-dev
配置
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
使用file-loader加载图片
npm install file-loader –save-dev
配置file-loader
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ['file-loader']
}
]
}
使用plugin
插件(Plugin)是用来扩展webpack功能的。
HtmlWebpackPlugin
HtmlWebpackPlugin插件默认会生成一个index.html文件,用来替换原有文件,index.html文件的内容也会随着替换而改变。
安装插件
npm install html-webpack-plugin --save-dev
使用插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new HtmlWebpackPlugin({
title: 'Home',
filename: 'home.html'
})
]
CleanWebpackPlugin
该插件会在构建之前清理dist/文件夹。
安装插件
npm install clean-webpack-plugin --save-dev
配置插件
const CleanWebpackPlugin = require('clean-webpack-plugin');
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'Home',
filename: 'home.html'
})
]
使用devServer
安装webpack-dev-server
```bash
npm install webpack-dev-server --save-dev
配置
devServer: {
contentBase: path.join(__dirname, 'dist'),
port: 8080,
index: 'home.html',
hot: true,
open: true,
https: true
}
核心概念
Entry,入口,webpack执行打包任务的第一步从entry开始,可以看作是输入。
Output,输出,webpack进行一系列的处理之后,输出代码结果。
Loader,模块加载(转换)器,用于将模块的内容转换成我们想要的结果内容。
Plugin,扩展插件,用来扩展webpack的功能。
Module,模块,在webpack中,一切皆模块,每一个模块对应一个文件。Webpack会从entry开始,递归查找所有依赖的模块。
Chunk,代码块,一个chunk由多个模块组合而成,用于代码的合并与分割。
配置
昨天只是粗略讲解了webpack的基础核心功能,今天会讲解一下webpack常用的一些配置选项,供以后参考使用。
配置webpack的方法有如下两种:
1、通过一个JavaScript文件描述配置,例如,webpack.config.js配置文件。
2、执行webpack命令时通过命令行参数传入,例如,webpack --entry index.js --output mian.js
这两种方式也可以相互配合使用,例如,通过命令行参数传入选项 --config 指定配置文件,同时在webpack.config.js文件中指定其他配置选项。
入口
entry用于配置模块的入口,可以认为是输入,webpack构建的第一步就是从入口开始,搜索并递归解析出入口依赖的所有其他模块。
Context
webpack在寻找相对路径的文件时,会以context作为根目录,其默认是执行webpack命令时所在的工作目录。如果想改变context选项的默认配置,则可以在配置文件中修改它:
const path = require(‘path’);
module.exports = {
context: path.resolve(__dirname, ‘src’);
};
注意:context选项的值必须是一个绝对路径。此外,还可以在启动webpack时使用–context参数来设置。
之所以先介绍context选项,是因为接下来要讲的Entry的路径及其所依赖的其他模块的路径可能会采用相对于context的路径来指定,context会影响到这些相对路径所指向的真实文件。
Entry
entry选项的值可以是如下三种形式中的一种,也可以相互结合使用:
string,入口模块的文件路径,可以是相对路径,例如
module.exports = {
entry: ‘./home.js’
};
array,字符数组,由入口文件路径组成的数组,例如
module.exports = {
entry: [‘./home.js’, ‘./about.js’, ‘./contact.js’]
};
object,对象,配置多个入口,例如
module.exports = {
entry: {
home: ‘./home.js’,
about: ‘./about.js’,
contact: ‘./contact.js’
}
};
Chunk
chunk 表示一个文件,默认情况下 webpack 的输入是一个入口文件,输出也是一个文件, 这个文件就是一个 chunk,chunkId 就是产出时给每个文件一个唯一标识 id,chunkhash 就是文件内容的 md5 值,name 就是在 entry 中指定的 key 值。
webpack会为每个生成的chunk取一个名称,chunk的名称和Entry的配置有关。
如果entry选项的值是一个字符串或数组,则Chunk名称为main。
如果entry选项的值是一个对象,则属性名即是Chunk的名称,属性值表示入口文件。
注意:
1、当 entry 为数组的时候,webpack 会把数组里所有文件打包成一个 js 文件
2、当 entry 为对象的时候,webpack 会把对象里的文件分别打包成多个文件
输出(Output)
output选项用于配置如何输出最终想要的代码。output是一个对象,里面包含了一系列的选项,接下来我们来介绍一下这些选项。
output.filename
这个选项决定着每个输出文件的名称。输出文件会被写入到output.path选项指定的目录中。
对于单个入口点来说,则可以将它写成静态不变的名称:
module.exports = {
entry: ‘./home.js’,
output: {
filename: ‘bundle.js’,
path: path.resolve(__dirname, ‘dist’)
}
};
但是,当通过指定多个入口点、代码拆分或各种插件创建多个bundle时,你应该使用以下给出的方式之一为每个包提供唯一的名称。
使用入口名称
module.exports = {
//…
output: {
filename: ‘[name].bundle.js’
}
};
使用内部chunk id
module.exports = {
//…
output: {
filename: ‘[id].bundle.js’
}
};
使用为每次构建生成的唯一哈希:
module.exports = {
//…
output: {
filename: ’ [name].[hash].bundle.js’
}
};
使用基于每个块内容的哈希:
module.exports = {
//…
output: {
filename: ‘[chunkhash].bundle.js’
}
};
使用为提取的内容生成的哈希:
module.exports = {
//…
output: {
filename: ‘[contenthash].bundle.css’
}
};
使用函数返回文件名:
module.exports = {
//…
output: {
filename: (chunkData) => {
return chunkData.chunk.name === ‘main’ ? ‘[name].js’: ‘[name]/[name].js’;
},
}
};
内置变量除了name,还包括如下列表中所示的变量。
id,chunk的唯一标识,从0开始
name,chunk的名称
hash,chunk唯一标识的hash值
chunkhash,根据chunk内容计算出来的hash值