简单使用
安装
在命令行中依次输入
mkdir webpack-demo
cd webpack-demo
// 创建 package.json,这里会问一些问题,直接回车跳过就行
npm init
// 推荐这个安装方式,当然你也安装在全局环境下
// 这种安装方式会将 webpack 放入 devDependencies 依赖中
npm install --save-dev webpack
然后按照下图创建文件
在以下文件写入代码
// sum.js
// 这个模块化写法是 node 环境独有的,浏览器原生不支持使用
module.exports = function(a, b) {
return a + b
}
// index.js
var sum = require('./sum')
console.log(sum(1, 2))
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="./build/bundle.js"></script>
</body>
</html>
现在我们开始配置最简单的 webpack,首先创建 webpack.config.js
文件,然后写入如下代码
// 自带的库
const path = require('path')
module.exports = {
entry: './app/index.js', // 入口文件
output: {
path: path.resolve(__dirname, 'build'), // 必须使用绝对地址,输出文件夹
filename: "bundle.js" // 打包后输出文件的文件名
}
}
现在我们可以开始使用 webpack 了,在命令行中输入
node_modules/.bin/webpack
没问题的话你应该可以看到类似的样子
可以发现原本两个 JS 文件只有 100B,但是打包后却增长到 2.66KB,这之中 webpack 肯定做了什么事情,我们去 bundle.js
文件中看看。
把代码简化以后,核心思路是这样的
var array = [(function () {
var sum = array[1]
console.log(sum(1, 2))
}),
(function (a,b) {
return a + b
})
]
array[0]() // -> 3
因为 module.export
浏览器是不支持的,所以 webpack 将代码改成浏览器能识别的样子。现在将 index.html
文件在浏览器中打开,应该也可以看到正确的 log。
我们之前是在文件夹中安装的 webpack,每次要输入 node_modules/.bin/webpack
过于繁琐,可以在 package.json
如下修改
"scripts": {
"start": "webpack"
},
然后再次执行 npm run start
,可以发现和之前的效果是相同的。简单的使用到此为止,接下来我们来探索 webpack 更多的功能。
Loader
Loader 是 webpack 一个很强大功能,这个功能可以让你使用很多新的技术。
Babel
Babel 可以让你使用 ES2015/16/17 写代码而不用顾忌浏览器的问题,Babel 可以帮你转换代码。首先安装必要的几个 Babel 库
npm i --save-dev babel-loader babel-core babel-preset-env
先介绍下我们安装的三个库
- babel-loader 用于让 webpack 知道如何运行 babel
- babel-core 可以看做编译器,这个库知道如何解析代码
- babel-preset-env 这个库可以根据环境的不同转换代码
接下来更改 webpack-config.js
中的代码
module.exports = {
// ......
module: {
rules: [
{
// js 文件才使用 babel
test: /\.js$/,
// 使用哪个 loader
use: 'babel-loader',
// 不包括路径
exclude: /node_modules/
}
]
}
}
配置 Babel 有很多方式,这里推荐使用 .babelrc 文件管理。
// ..babelrc
{
"presets": ["babel-preset-env"]
}
现在将之前 JS 的代码改成 ES6 的写法
// sum.js
export default (a, b) => {
return a + b
}
// index.js
import sum from './sum'
console.log(sum(1, 2))
执行 npm run start
,再观察 bundle.js
中的代码,可以发现代码被转换过了,并且同样可以正常 输出3。
当然 Babel 远不止这些功能,有兴趣的可以前往官网自己探索。
处理图片
这一小节我们将使用 url-loader
和 file-loader
,这两个库不仅可以处理图片,还有其他的功能,有兴趣的可以自行学习。
先安装库
npm i --save-dev url-loader file-loader
创建一个 images
文件夹,放入两张图片,并且在 app
文件夹下创建一个 js 文件处理图片
,目前的文件夹结构如图
// addImage.js
let smallImg = document.createElement('img')
// 必须 require 进来
smallImg.src = require('../images/small.jpeg')
document.body.appendChild(smallImg)
let bigImg = document.createElement('img')
bigImg.src = require('../images/big.jpeg')
document.body.appendChild(bigImg)
接下来修改 webpack.config.js
代码
module.exports = {
// ...
module: {
rules: [
// ...
{
// 图片格式正则
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: [
{
loader: 'url-loader',
// 配置 url-loader 的可选项
options: {
// 限制 图片大小 10000B,小于限制会将图片转换为 base64格式
limit: 10000,
// 超出限制,创建的文件格式
// build/images/[图片名].[hash].[图片格式]
name: 'images/[name].[hash].[ext]'
}
}
]
}
]
}
}
运行 npm run start
,打包成功如下图
可以发现大的图片被单独提取了出来,小的图片打包进了 bundle.js
中。
在浏览器中打开 HTML 文件,发现小图确实显示出来了,但是却没有看到大图,打开开发者工具栏,可以发现我们大图的图片路径是有问题的,所以我们又要修改 webpack.config.js
代码了。
module.exports = {
entry: './app/index.js', // 入口文件
output: {
path: path.resolve(__dirname, 'build'), // 必须使用绝对地址,输出文件夹
filename: "bundle.js", // 打包后输出文件的文件名
publicPath: 'build/' // 知道如何寻找资源
}
// ...
}
最后运行下 npm run start
,编译成功了,再次刷新下页面,可以发现这次大图被正确的显示了。下一小节我们将介绍如何处理 CSS 文件。
处理 CSS 文件
添加 styles
文件夹,新增 addImage.css
文件,然后在该文件中新增代码
img {
border: 5px black solid;
}
.test {border: 5px black solid;}
这一小节我们先使用 css-loader
和 style-loader
库。前者可以让 CSS 文件也支持impost
,并且会解析 CSS 文件,后者可以将解析出来的 CSS 通过标签的形式插入到 HTML 中,所以后面依赖前者。
npm i --save-dev css-loader style-loader
首先修改 addImage.js
文件
import '../styles/addImage.css'
let smallImg = document.createElement('img')
smallImg.src = require('../images/small.jpeg')
document.body.appendChild(smallImg)
// let bigImg = document.createElement('img')
// bigImg.src = require('../images/big.jpeg')
// document.body.appendChild(bigImg)
然后修改 webpack.config.js
代码
module.exports = {
// ...
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
}
]
},
]
}
}
运行下 npm run start
,然后刷新页面,可以发现图片被正确的加上了边框,现在我们来看一下 HTML 的文件结构
从上图可以看到,我们在 addImage.css
文件中写的代码被加入到了 style
标签中,并且因为我们开启了 CSS 模块化的选项,所以 .test
被转成了唯一的哈希值,这样就解决了 CSS 的变量名重复问题。
但是将 CSS 代码整合进 JS 文件也是有弊端的,大量的 CSS 代码会造成 JS 文件的大小变大,操作 DOM 也会造成性能上的问题,所以接下来我们将使用 extract-text-webpack-plugin
插件将 CSS 文件打包为一个单独文件
首先安装 npm i --save-dev extract-text-webpack-plugin
然后修改 webpack.config.js
代码
const ExtractTextPlugin = require("extract-text-webpack-plugin")
module.exports = {
// ....
module: {
rules: [
{
test: /\.css$/,
// 写法和之前基本一致
loader: ExtractTextPlugin.extract({
// 必须这样写,否则会报错
fallback: 'style-loader',
use: [{
loader: 'css-loader',
options: {
modules: true
}
}]
})
]
}
]
},
// 插件列表
plugins: [
// 输出的文件路径
new ExtractTextPlugin("css/[name].[hash].css")
]
}
运行下 npm run start
,可以发现 CSS 文件被单独打包出来了
但是这时候刷新页面会发现图片的边框消失了,那是因为我们的 HTML 文件没有引用新的 CSS 文件,所以这里需要我们手动引入下,在下面的章节我们会通过插件的方式自动引入新的文件。