前言:本文描述一个小白学习webpack4从零开始的完整过程全纪录,能够说彻底以一个初学者的口吻来写这篇文章的,与此同时这篇文章还会长期更新,不足之处还望大佬雅正!javascript
对于小白来讲,看到一些专业的术语就脑袋疼
什么是webpack?
简单来说,就是把咱们写好的代码打包。
怎么个打包法,压缩代码,相同资源抽取,处理一下浏览器不识别的代码(如ES6+、TS、SASS等)。
一句话,用不到就扔掉,能压缩就压缩,能兼容就兼容css
npm是世界上最大的软件注册表,使用npm咱们能够快速安装各类大小型软件和库
下载:在node.js中都自带了npm,因此咱们下载node.js便可
node.js官网: https://nodejs.org/en/
下载完后,咱们能够在dos命令行下能够看到node.js的版本和npm的版本 node -v npm -vhtml
①、新建练习文件目录 ex1
①、在ex1目录下新建源文件目录 src
②、在src目录下新建入口文件 index.js
造成的目录结构以下:java
package.json文件定义了这个项目所须要的各类模块,以及项目的配置信息(好比名称、版本、许可证等元数据)。
在ex1目录下使用命令:node
npm init -y
init指令会询问一系列的问题,并将你的配置写成一个package.json文件。
若是使用了-f|--force|-y|--yes这些参数,那么会生成一个默认的package.json文件。
这个init过程很快,能够看到在ex1目录下多了个package.json文件webpack
提示:webpack4.0以上版本的webpack的脚手架webpack-cli已经被分离出来,须要另外安装。
安装webpack分为全局安装和本地安装(局部安装)web
全局安装(不推荐) npm install webpack webpack-cli -g
(-g就是全局安装)
本地安装 npm install webpack webpack-cli -D
(-D 就是安装到开发环境)
安装成功后如图所示:正则表达式
再来看下咱们的文件目录发生了什么变化:
node_modules文件夹主要是用于放用包管理工具下载安装了的包,这个文件的内容有不少
package-lock.json锁定了包的版本,确保可以避免包版本不一样产生的问题。chrome
npx 会帮你执行依赖包里的二进制文件。
npx会自动找到node_modules/bin 的webpack.cmd去执行,免去了script的配置shell
在src的目录下新建一个名为 demo1.js的文件
在demo1.js 中写入以下内容
module.exports = '这是common.js的语法,在node端运行,把我用webpack打包以后,就能够在浏览器上运行了'
在index.js中写入以下内容
let d1 = require('./demo1.js'); console.log(d1);
使用命令进行打包
npx webpack
结果如图:
打包后咱们能够发如今ex1目录下多了个 dist 文件夹
这个dist 文件夹中有个 main.js文件,是打包后的js文件
为了查看结果,咱们能够在dist目录下新建一个 index.html 文件
在index.html使用script标签引入main.js
<script src="./main.js"></script>
在控制台里面就能够看到这么一句话:'这是common.js的语法,在node端运行,把我用webpack打包以后,就能够在浏览器上运行了'
细心的你可能会发现上面打包的结果有一个 黄色的警告
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concep...
黄色警告意为webpack没有指定是开发模式development 仍是 生产模式production
那咱们就能够在命令后面加上 --mode development
看,是否是没有了黄色警告提示。
npx的缺点:虽然使用npx能够快速的帮咱们打包,可是不够灵活,好比打包后文件夹名字都是固定 dist,所以咱们须要定义webpack打包的配置文件,这样才能够为所欲为的打包
咱们如今ex1的目录下新建一个名为 webpack.config.js 文件
因为webpack是基于node,因此要遵循common.js规范
入口起点(entry point)指示 webpack 应该使用哪一个模块,来做为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
entry 属性的单个入口语法
module.exports = { entry: './src/index.js' };
output 属性告诉 webpack 在哪里输出它所建立的 bundles,以及如何命名这些文件。
默认值为 ./dist。
在 webpack 中配置 output 属性的最低要求是,将它的值设置为一个对象,包括如下两点:
webpack.config.js
// 基于node,遵循common.js规范 const path = require('path') // 引入node.js Path 模块 module.exports = { entry: './src/index.js', // 入口 output: { filename: 'bundle.js', path: path.join(__dirname, './build') } }
因为path要求为绝对路径,因此咱们使用了 path.join 拼接路径这个node的语法,
node不能在浏览器端运行,因此咱们能够利用 vscode 编辑器 的 Code Runner 插件来查看当前路径的结果
在webpack.config.js保留以下代码:
const path = require('path') // 引入node.js Path 模块 console.log(path.join(__dirname, './build'));
结果如图:
在webpack.config.js配置好出入口后,那咱们能够尝试着打包了
打包结果如图:
在ex1的目录下多了个 build文件以及其目录下的bundle.js文件
那么说明了咱们的配置是成功的!
能够参考阮一峰老师的博客:http://www.ruanyifeng.com/blo...
npm 容许在package.json文件里面,使用scripts字段定义脚本命令。
npm 脚本。它的优势不少
在咱们原有的package.json中,咱们能够发现有一个这样"scripts"字段
"scripts": { "test": "echo \"Error: no test specified\" && exit 1" }
所以咱们能够尝试使用 npm test 命令看下会有什么结果
结果执行了echo语句
咱们能够利用npm脚原本替代webpack语句,咱们修改一下test字段对应为webpack命令
"scripts": { "test": "webpack" }
接着咱们尝试使用 npm test 命令来运行一下
能够发现咱们已经打包成功了。
那么有的朋友就会问了,必定要test吗?
好,咱们随便来个命令,就 abc
在test字段下,咱们加多一个abc字段,以下面代码所示:
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "abc": "webpack" }
执行 npm abc 命令看看结果怎样
哎,奇怪了呀,这是什么状况,有一点很明确的是,并无执行webpack打包执行命令。
不急不急,咱们先来看下提示先:
注意到这句话:where <command> is one of:
也就是说咱们的命令应该下面那些,也就是说只能使用 npm <command>,这个command应该是提示其中之一,咱们在提示中能够发现有 test 命令
也就是说只要知足了上面字段的其中之一,就可使用 npm <command>
可是这些命令是npm自带的,并非全部均可以用来执行script脚本的。
除此以外,还有一个start命令也是能够直接执行的,如图
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack" }
那么问题来了,咱们怎么知道哪些命令能够直接执行script,要一个个尝试岂不是很麻烦吗?
此时咱们可使用npm run <command> 命令来直接执行脚本
使用npm run script执行脚本的时候都会建立一个shell,而后在shell中执行指定的脚本。
因此此次咱们不用再为使用什么script字段而烦恼了。
好,咱们再来试一下abc字段
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "abc": "webpack" }
哈哈,终于成功了!
在以前我有讲到过,黄色警告是因为没有设置模式而出现,那时候提的方法是每次都要在执行打包的命令的时候加上这么一句 --mode development/production
那这样是否是很麻烦,因此咱们能够在配置文件这样定义
mode: 'development'
那么,此时咱们的webpack.config.js的文件内容以下:
// 基于node,遵循common.js规范 const path = require('path') // 引入node.js Path 模块 module.exports = { entry: './src/index.js', // 入口 output: { filename: 'bundle.js', path: path.join(__dirname, './build') }, mode: 'development' // 模式 }
此时,咱们再打包试一下,结果如图:
咱们可清楚地看到黄色警告已经去掉了
在咱们的package.json文件里,能够看到这么一个字段 "devDependencies"
除此以外还有一个与之相关的字段叫 “dependencies ”
*devDependencies 与 dependencies 的区别
devDependencies 里面的模块只用于开发环境(development)
而 dependencies 里面的模块是须要发布到生产环境(production) 。好比咱们有一个项目要用到jQuery,在线上运行的时候若是没有jQuery包的依赖运行就会报错,这时候就应该把这个依赖写入dependencies
而咱们使用的一些构建工具如webpack这些只是在开发中使用的包,上线之后就和这些包不要紧了,因此将这种依赖写入 devDependencies
在咱们使npm安装模块的时候,都会使用一个命令
npm install(能够简写为 npm i)
与此对应的还有这两个重要的对应参数:
--save (能够简写为-S)
--save-dev (能够简写为-D)
①、npm install m
②、npm install m –save:
②、npm install m –save-dev:
webpack-dev-server 可以用于快速开发应用程序
里面包含了不少丰富的功能,其中最为重要的固然是可以监听本地代码的修改,利用热加载自动刷新浏览器,这样大大地方便了咱们进行代码的调试
第一步:安装webpack-dev-server
在前面,我有讲到关系依赖这方面的知识,关于 devDependencies 与 dependencies 的区别,相信你们都能看懂。很明显 webpack-dev-server 只是用来本地调试的,上线以后就用不上了,那么咱们能够很明确将webpack-dev-server 放到devDependencies中
执行以下命令:
npm install webpack-dev-server -D
安装好后,咱们再来看一下package.json文件的变化
第二步:配置webpack-dev-server
配置项目 | 描述 | 注意 |
---|---|---|
contentBase | 告诉服务器从哪一个目录中提供内容 | 推荐使用绝对路径。 |
compress | 一切服务都启用 gzip 压缩 | compress: true |
host | 指定使用一个 host。默认是 localhost | 能够外部服务器访问 |
https | 默认状况下,dev-server 经过 HTTP 提供服务 | https: true |
open | 启用 open 后,dev server 会打开浏览器 | 默认浏览器,能够指定其余 |
port | 指定要监听请求的端口号 | 默认8080 |
其实webpack-dve-server的配置项目远远不止这些,这里只是列举了一部分
咱们先在package.json中添加script脚本
"dev": "webpack-dev-server"
①、contentBase解析
再回来看下咱们的webpack.json.js文件,webpack-dve-server配置的字段为devServer,咱们先不配置先,看看会怎么样?
此时webpack.json.js的内容
// 基于node,遵循common.js规范 const path = require('path') // 引入node.js Path 模块 module.exports = { entry: './src/index.js', // 入口 output: { filename: 'bundle.js', path: path.join(__dirname, './build') }, mode: 'development' // 模式 }
执行命令:
npm run dev
看下结果:
如今能够清楚的看到,咱们的项目已经运行在 http://localhost:8080
好的,那么咱们在浏览器输入这个url看看这个页面会显示什么
如图所示:
这里只显示了咱们整个文件的目录
默认状况下,contentBase将使用当前工做目录做为提供内容的目录
为了证实这点,咱们在ex1的目录下新建一个index.html
如今的目录结构以下:
如今在根目录下的index.html写入以下内容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>index</title> </head> <body> 这是根目录的index.html </body> </html>
好,如今在从新执行命令 npm run dev
而后在浏览器打开http://localhost:8080 页面
咱们就能够发现结果不一样了
那么这就能够证实了
默认状况下,contentBase将使用当前工做目录做为提供内容的目录
好,如今咱们要把内容目录设在build文件夹下
咱们如今build目录下新建一个index.html文件
写入以下内容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> 这是build文件下的index.html </body> </html>
这时候回到咱们的配置文件(webpack.config.js)
写入以下内容:
devServer: { contentBase: './build' }
如今webpack.config.js的内容以下:
// 基于node,遵循common.js规范 const path = require('path') // 引入node.js Path 模块 module.exports = { entry: './src/index.js', // 入口 output: { filename: 'bundle.js', path: path.join(__dirname, './build') }, mode: 'development', // 模式 devServer: { contentBase: './build' } }
好,如今万事俱备,只欠东风。如今咱们再从新执行 npm run dev 命令
一样的,在浏览器能够看到结果
②、open
启用 open 后,devServer 会打开浏览器。
在devServer设置以下:
open: true
注意,这里的true是布尔值,不是字符串
在启用命令 npm run dev后,devServer 会打开默认浏览器
你们用window通常都是IE浏览器做为默认浏览器
那么此时若是咱们想使用谷歌浏览器来启动应该怎么设置呢?
此时,咱们能够在package.json对script脚本进行设置,
// 打开默认浏览器 "dev": "webpack-dev-server --open" // 打开谷歌浏览器 "dev": "webpack-dev-server --open chrome" // 打开火狐浏览器 "dev": "webpack-dev-server --open firefox"
*提示:若是在script设置了--open,那么能够不用在配置文件设置open字段了
因为使用webpack打包后,原来的代码通过压缩,去空格,bable的编译以后,已经变成咱们不认识的代码了,为了方便咱们调试调式代码,定位bug,source map就出现了
在webpack.config.js中,devtool选项用于控制是否生成,以及如何生成 source map。
loader 用于对模块的源代码进行转换。loader 可使你在 import 或"加载"模块时预处理文件。
webpack自己只能处理javascript文件,而对于css文件须要loader来处理
对于css处理,咱们经常使用的有这两种loader:css-loader 和 style-loader
使用命令安装这两个loader
npm i -D style-loader css-loader
接下来在src文件下新建名为 style 的文件夹,在style 下新建名为 index.css 文件
为了让效果更加直观,往 index.css 文件写入以下内容
body{background-color: yellowgreen;}
接着在咱们 src目录下的 index.js 文件中使用ES6的模块语法 import 将index.css文件导入进来
import './style/index.css'
咱们先不配置loader,看看浏览器会提示什么
执行 npm run dev 命令,看看会发生什么,如图所示:
提示模块解析失败,须要loader进行处理
有三种使用 loader 的方式:
咱们选择在webpack.config.js中配置loader
基本写法以下:
module: { rules: [ { test: /\.css$/, // 利用正则表达式匹配文件名后缀为css的文件 use: ['style-loader', 'css-loader'] // 一组loader的执行顺序默认是从右向左 } ] }
接着,咱们再从新执行 npm run dev命令,页面如图所示:
说明咱们css文件有效果了,再来看下网页元素
效果如图,能够看到是之内联样式插入到html
插件目的在于解决 loader 没法实现的其余事。
这个插件用来简化建立服务于 webpack bundle 的 HTML 文件,因为一般在打包中包含一些含有hash值的名字,而这些名字在每次编译的时候都发生变化的时候对咱们开发人员很麻烦,利用这个插件,咱们能够利用这个插件捆绑式这些文件方便咱们的开发。
执行安装命令
npm i -D html-webpack-plugin
在webpack.config.js 配置以下:
// 基于node,遵循common.js规范 const path = require('path') // 引入node.js Path 模块 const HtmlWebpackPlugin = require('html-webpack-plugin') // 引入HtmlWebpackPlugin module.exports = { entry: './src/index.js', // 入口 output: { filename: 'bundle.js', path: path.join(__dirname, './build') }, mode: 'development', // 模式 devServer: { contentBase: './build' }, module: { rules: [ { test: /\.css$/, // 利用正则表达式匹配文件名后缀为css的文件 use: ['style-loader', 'css-loader'] // 一组loader的执行顺序默认是从右向左 } ] }, plugins: [ new HtmlWebpackPlugin() ] }
在这里,咱们这个插件作了两步工做:
const HtmlWebpackPlugin = require('html-webpack-plugin') plugins: [ new HtmlWebpackPlugin() ]
接下来,咱们须要在src目录下新建模板文件,名为 template.html,咱们打包后的文件都已这个html文件为模板
在模板html写入以下内容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板文件</title> </head> <body> 使用模板文件 </body> </html>
这里咱们只是简单的使用两个参数
选项 | 描述 | 注意 |
---|---|---|
filename | 就是html文件的文件名,默认是index.html | |
template | 生成的文件所依赖文件模板的路径 |
plugins的配置以下
plugins: [ new HtmlWebpackPlugin({ filename: 'index.html', template: './src/template.html', }) ]
好的,如今全部都配置好了,咱们来测试一下
执行命令 npm run dev
能够发现,运行项目时使用的是模板文件
如今,再来测试一下打包文件
咱们把原来的build文件删除(固然能够不删,由于会覆盖)
执行命令 npm run abc
此时,咱们能够发现 build 目录下 index.html是这个样子的
直接就帮咱们用script标签插入了bundle.js
总结:入门不易,掌握更难,纸上得来终觉浅,绝知此事要躬行!