【webpack浅析】webpack之深入浅出
本文主要讲解两个方面。分别是 深入了解webpack 和 从0开始配置vue项目。一:深入了解webpack1、webpack干什么的总的来说,webpack是一个资源综合处理中心。这名字起的是不是前无古人,是不是高端大气?!这里我要利用高深的比喻修辞手法和配图(见配图 1.1)大概齐的解释一下webpack。webpack其实可以看做是一个半自动(之所以是半自动,是需要我们自己进行很多的配置)工
前言
本文旨在讲解webpack的基本配置。从0开始,由浅入深地讲解webpack是如何工作和配置的,一步一步的带你揭开webpack的神秘面纱。
如有纰漏,敬请指正。
目录
深入了解webpack
1、webpack干什么的
总的来说,webpack是一个 资源综合处理中心 。为了说明这个处理中心,这里我要利用一张图片(见配图 1.1)大概齐的解释一下webpack。webpack 其实可以看做是一个半自动(之所以是半自动,是需要我们自己进行很多的配置)工厂流水线。所有的前端资源,比如 图片,样式,js文件等等,一个接一个排好队伍,整齐划一的进入流水线,根据设定好的程序(就是webpack的那些配置),一一处理加工(根据各种module规则的配置进行解析,根据一些plugins进行压缩等等的处理),生产出最终的产品(也就是我们的dist包,里边包含我们处理好的前端项目资源)。
2、webpack的核心概念
毫不夸张的说,webpack的配置项没有一万也有八千。如果将每一个API都研究透彻,伤神费力效率低。所以,看问题,要看本质,而看本质,就要抓住核心。那么 webpack的核心模块和配置主要有哪些? 这里列举了几个主要的:
- entry
官方文档:https://www.webpackjs.com/configuration/entry-context/#entry
entry:是webpack的入口,这里配置项目入口文件的地址。由此开始进入webpack的构建流程。
- output
官方文档:https://www.webpackjs.com/configuration/output/
output:输出资源的信息配置,包含输出资源的文件名(filename),输出资源的放置路径(path)等等。
- module
官方文档:https://www.webpackjs.com/configuration/module/
module:里边规定了如何去解析和转义各种文件类型(主要是 rules 的loaders配置)。
- resolve
官方文档:https://www.webpackjs.com/configuration/resolve/
resolve:制定了如何去寻找模块依赖。(比如指定 alias 来简化文件路径 )
- plugins
官方文档:https://www.webpackjs.com/configuration/plugins/
plugins:在某个时机(生命周期)去对资源进行操作的方法。
以上几部分,就是webpack最核心的部分。
下面我们从0开始,配置和使用webpack来处理和打包。
3、从0开始配置项目
我们来通过一个项目,一个一个的介绍这些项目如何配置和工作的。
// 创建一个文件夹 里边执行
npm init -y
// 得到package.json,在文件夹中安装 webpack webpack-cli
npm i -D webpack webpack-cli
// 根目录创建 webpack.config.js 文件
项目结构如下:
默认情况下,webpack.config.js 代表webpack的配置。当然文件名也是可以更改的,通过 webpack 命令进行更改:
webpack --congfig xxxxx(你自己的文件名,比如webpack.my.config.js)
webpack配置 - 处理文件类型
文件中添加src文件夹,里边首先来一个主文件,也就是 入口文件 main.js, 然后再来一个js文件夹,写两个简单的方法,目的是引入main.js,就像这样:
在 入口文件中引入:
import {
add
} from './js/math'
console.log(add(1, 2));
最简单的入口文件已经完成了。
A、处理 js文件
开始配置webpack.config.js:
module.exports = {
// entry 入口文件
// 告诉 webpack 要解析这个文件中引入依赖和资源
entry: './src/main.js'
}
有了入口,就应该想到出口 output:
const path = require('path');
module.exports = {
entry: './src/main.js',
// 出口
output: {
// 设置打包生成文件的名称以及文件路径
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
现在最基本的webpack配置已经完成。我们准备执行一下,看看结果。
怎么执行呢?
其实三种执行办法:
- webpack
- npx webpack
- scripts
在package.json中的scripts配置脚本:
{
"name": "webpack_demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
}
}
最后一种方式是不是让你想起了 npm run dev.(笑脸.jpg).
既然如此,我们将在后边都是用 脚本方式。
我们看到上图,最终的结果终于是打包成功了。
验证一下吧,在生成的dist文件中手动添加一个 html文件,把生成的bundlejs引入,在浏览器中看看吧。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="./bundle.js"></script>
</body>
</html>
执行一下,结果为
嗯,不错,验证成功,说明这个打包都没错。
到目前为止,我们没有任何处理关于js文件的配置。这正好印证了webpack是天生处理js文件的好帮手。但是我们知道,还有更高阶的js呢,比如 ES6,甚至ES10。这些高阶的写法,除了chrome等少数浏览器很好的支持,还有一些浏览并不能很好的支持。那么这时候我们需要将这些高阶的写法转化为更加兼容的写法。所以,这时候又要提到了babel。
要使用babel,首先要安装babel-loader。
npm i -D babel-loader
当webpack使用babel-loader处理文件时,babel-loader实际上调用了babel-core的api,因此也必须安装babel-core:
npm install -D babel-core
babel有几种规则都可以实现对ES6语法的转码,如babel-preset-es2015、babel-preset-latest、babel-preset-env,要安装
babel-preset-env的作用是告诉babel使用哪种转码规则进行文件处理:
npm install -D babel-preset-env
注意:babel-loader@8 requires Babel 7.x (the package '@babel/core'). If you'duse Babel 6.x ('babel-core'), you should install 'babel-loader@7'. 就是说注意你的babel-core和babel-loader要匹配。否则报错。
在package.json中配置规则:
...
"babel": {
"presets": [
"env"
]
},
...
在webpack.config.js中配置loader:
...
{
test: /\.js$/,
exclude: /node_modules/,
use: ['babel-loader']
},
...
这样成功处理js文件。(如果需要验证,找一个IE低版本浏览器,写一些promise等语法进行验证,看看是否能打包成功)
B、处理css文件
很显然,前端资源不仅仅只有js文件。还有css文件。我们在文件中写个css文件,并引入入口文件中。
执行一下,毫无意外的报错了。报错信息很明显:You may need an appropriate loader to handle this file type。
直接告诉你,你需要一个合适的 loader 来处理这类型的文件。什么loader? 当让是css-loader,style-loader。
// 处理css 需要用到style-loader css-loader
// 安装吧
npm i -D style-loader css-loader
安装完毕之后,又要配置loader了。
let path = require('path');
function resolve (url) {
return path.resolve(__dirname, url)
}
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.js',
path: resolve('dist')
},
// 开始配置loader
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
}
这里要注意:loader的解析顺序是从后往前。
先交给 css-loader 处理css文件,处理完成之后再交给 style-loader处理,然后动态的向我们的html文件的head中添加style标签,注入css,最终就像这样的:
现在css文件也成功的处理好了。
C、处理图片文件
现在我们准备在引入图片资源。
为了方便,在css文件中引入一个背景图片。
我们可以直接打包。不过,也许你因为上边css-loader而变得有先见之明。这次也一定会报错。所以,我们同样的要安装处理图片资源的loader。
// 处理图片类的loader有两个: url-loader和file-loader
npm i -D url-loader file-loader
这一次又是两个loader。但是和css处理的不同。他们两个的只需要其中的一个即可。虽然功能差不多,但是他们还是有一些区别:
1、请记住,url-loader依赖于file-loader。如果用url-loader,一定要安装 file-loader。
2、url-loader处理文件时,可以设置文件大小限制(limit)。如果图片文件小于这个限制,就会被直接处理为base64形式。大于这个限制,就会直接输出到指定文件中。
好了,我们来配置一下处理图片的loader:
const path = require('path');
function resolve(dir) {
return path.resolve(__dirname, dir)
}
module.exports = {
...
module: {
rules: [
...
// 图片的配置
{
test: /\.(png|jpe?g|gif)/,
use: [
{
loader: 'url-loader',
options: {
// 小于8k的图片将被转为base64
limit: 8192,
// 输出的文件名字
name: '[name].[hash:8].[ext]',
// 输出的路径
outputpath: 'images/'
}
}
]
}
]
}
}
打包验证一下:
如上,图片也成功打包成功。小于8k成功被处理为base64。实际上,这两个loader不仅仅用来处理图片,同时也可以处理多种格式的文件,比如 pdf,ttf等。
webpack配置 - 前端工程自动化配置
A、HtmlWebpackPlugin
我们每次验证的时候都得自己手动的在 dist 包内添加index.html,手动引入 bundle.js。这样做真的很不智能,很不科学。有个插件j叫 HtmlWebpackPlugin。能帮助解决这个问题,他就是在打包之后拷贝一份src目录下的indexhtml,自动引入bundle.js。
安装一下吧:
npm install --save-dev html-webpack-plugin
在webpack.config.js中配置使用:
// webpack.config.js
// 引入htmlwebpackplugins
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exportd = {
...
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
}
构建一下试试:
看看,成功的拷贝了一份index.html,并引入 bundle.js。
B、webpack-dev-server
另外可能你也注意到了,每一次构建的时候都是直接打包的。但是我们在实际的开发环境下,不需要每次打包出dist,而是希望生成资源后,在浏览器打开index.html。那么个时候需要用到webpack-dev-server。
首先得安装webpack-dev-server:
npm i -D webpack-dev-server
在webpack.config.js中配置dev-server:
module.exports = {
...
devServer: {
// 告诉服务器从哪里提供内容
contentBase: path.join('dist'),
// 是否开启压缩
compress: true,
// 端口号
port: 9999
}
}
做了这些基础的配置,我们还需要在 package.json 中配置一下启动脚本以便支持我们的 npm run dev 和 npm run build。
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server",
"build": "webpack"
},
...
然后 npm run dev:
构建成功。并且看到该项目已经运行在了 我们配置的 9999 端口,在浏览器中打开:
自动的打开index.html,一切都正常。
那我现在想要在项目中改变一下box的样式:
改变index.css中的背景色: background: #096。
成功变成了颜色。
C、HMR(热更新)
但是这样有个问题。每次变化了,webpack-dev-server会整体刷新页面,造成效率低下。这时候就需要引入热更新的概念了 - HotModuleReplacementPlugin(简称 HMR)。
这个插件是webpack内置的不需要额外安装,配合 devServe中的hot配置项,就可以实现。在webpack.config.js中做出一些改变:
// 引入 webpack
const webpack = require('webpack')
module.exports = {
...
plugins: [
...
// 引入热更新模块
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9999,
// 开启热更新
hot: true
}
}
npm run dev ,打开localhost:9999成功打开页面。现在更改一下css文件,看看热更新有没有起作用。把index.css中的 box的背景色改变为 #d02;然后看看页面成功更新如下:
热更新也成功部署完毕了。
webpack配置 - 结合vue
上边大概介绍了一下前端工程使用webpack进行构建的过程。下面结合vue前端js框架,看看vue和webpack如何让结合。
首先肯定要安装vue
// 安装 vue
npm i -S vue
vue这种类型的文件,浏览器肯定不认识。仍然是需要loader去转义解析一下的,所以在安装 vue-loader
npm i -D vue-loader
另外还需要安装一个编译loader叫做vue-template-compiler,目的是把vue的template模板语法编译为render函数,以更高效的进行构建。
npm i -D vue-template-compiler
安装工作暂时告一段落。下面开始配置webpack.config.js:
module.exports = {
...
module: {
rules: [
...
// 新增vue-loader解释器
{
test: /\.vue$/,
include: resolve('src'),
use: ['vue-loader']
},
]
}
}
然后准备开始在入口文件中引入 vue,在引入vue之前需要src下创建一个App.vue文件,方便一会vue渲染。
然后开始改变入口文件,引入vue,并挂载到index.html中id为app的根节点上:
// 入口文件 main.js
import Vue from 'vue'
import App from './App.vue'
new Vue({
el: '#app',
render: h => h(App)
})
给index.html中添加一个id为app的div根节点:
看起来应该是可以了吧,直接 npm run dev 看看:
报错了。报错信息:vue-loader was used without the corresponding plugin.大概意思是 vue-loader在没有合适插件的情况下被使用了。也就说使用vue-loader还得要个插件,就是它 - VueLoaderPlugin。需要引入这个插件才能使vue-loader正常使用。好吧,配置一下plugins:
// webpack.config.js
// 引入VueLoaderPlugin
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
...
plugins: [
...
// 配置vue-loader 需要使用vueloaderplugin
new VueLoaderPlugin ()
]
}
重启服务。npm run dev ,打开localhost: 9999;
大功告成了。然后就开始享受你的vue项目吧。
深入浅出webpack的配置,写到这里基本就准备结束了。webpack的博大精深,本文提及的不及万一。所以大家还是没事多看看官方文档。
最终附上源码地址供参考之用: https://gitee.com/gitee__wang/basic_configuration_of_webpack
end~
更多推荐
所有评论(0)