一、介绍
官方文档:https://webpack.docschina.org/concepts/#entry
1.什么是webpack
webpack 是前端的一个项目构建工具,它是基于 Node.js 开发出来的一个前端工具。
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。
2.Webpack的工作方式
把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。
3.当我们在 控制台,直接输入 webpack 命令执行的时候,webpack 的执行流程
(1). 首先,webpack 发现,我们并没有通过命令的形式,给它指定入口和出口
(2). webpack 就会去 项目的 根目录中,查找一个叫做 webpack.config.js 的配置文件
(3). 当找到配置文件后,webpack 会去解析执行这个 配置文件,当解析执行完配置文件后,就得到了 配置文件中,导出的配置对象
(4). 当 webpack 拿到 配置对象后,就拿到了 配置对象中,指定的 入口 和 出口,然后进行打包构建
二、Webpack安装
//全局安装
npm install -g webpack
//安装到你的项目目录
npm install --save-dev webpack
三、初步使用webpack打包
1. 运行npm init -yes初始化项目,使用npm管理项目中的依赖包
(在终端中使用npm init -yes命令可以自动创建这个package.json文件)
2.安装webpack
npm install --save-dev webpack
3.创建src目录
4.在src目录中创建hello.js文件(写以下代码)
module.exports = function() { var hello = document.createElement('div'); hello.textContent = "Hi everybody!"; return hello; };
5.新建src/main.js,写入代码
var hello = require('./hello.js'); document.getElementById('content').appendChild(hello());
6.在src目录中创建index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>demo1</title> </head> <body> <!--要插入React组件的位置--> <div id="content"></div> <!--引入bundle.js--> <script src="bundle.js"></script> </body> </html>
7.创建webpack.config.js文件
//__dirname是node.js中的一个全局变量,它指向当前执行脚本所在的目录 module.exports = {//注意这里是exports不是export entry: __dirname + "/src/main.js",//唯一入口文件 output: {//输出目录 path: __dirname + '/build',//打包后的js文件存放的地方 filename: 'bundle.js'//打包后输出的js的文件名 }, };
8.项目打包(在终端输入webpack)
webpack //会生成build目录和bundle.js文件
四、使用webpack打包构建列表隔行变色案例
1. 运行npm init -yes初始化项目,使用npm管理项目中的依赖包
(在终端中使用npm init -yes命令可以自动创建这个package.json文件)
2、安装webpack
npm install --save-dev webpack
3、创建webpack.config.js
// 导入处理路径的模块 var path = require('path'); // 导出一个配置对象,将来webpack在启动的时候,会默认来查找webpack.config.js,并读取这个文件中导出的配置对象,来进行打包处理 module.exports = { entry: path.resolve(__dirname, 'src/js/main.js'), // 项目入口文件 output: { // 配置输出选项 path: path.resolve(__dirname, 'dist'), // 配置输出的路径 filename: 'bundle.js' // 配置输出的文件名 } }
4. 创建项目的src目录及src/js目录
5.在src目录中创建index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <!-- 注意: 不推荐直接在这里引用任何包和任何CSS文件 --> <!-- 因为 main 中的代码,涉及到了ES6的新语法,但是浏览器不识别 --> <!-- <script src="./main.js"></script> --> <!-- 通过 webpack 这么一个前端构建工具, 把 main.js 做了一下处理,生成了一个 bundle.js 的文件 --> <script src="../dist/bundle.js"></script> </head> <body> <ul> <li>这是第1个li</li> <li>这是第2个li</li> <li>这是第3个li</li> <li>这是第4个li</li> <li>这是第5个li</li> <li>这是第6个li</li> <li>这是第7个li</li> <li>这是第8个li</li> <li>这是第9个li</li> <li>这是第10个li</li> </ul> </body> </html>
6. 使用cnpm i jquery --save安装jquery类库
cnpm i jquery --save
7. 在src/js下创建main.js并书写各行变色的代码逻辑
import $ from 'jquery' $(function () { $('li:odd').css('backgroundColor', 'yellow') $('li:even').css('backgroundColor', function () { return '#' + 'D97634' }) })
8. 运行webpack
9.访问index.html
五、基于四(上面)实现webpack的实时打包构建
1. 由于每次重新修改代码之后,都需要手动运行webpack打包的命令,比较麻烦,所以使用`webpack-dev-server`来实现代码实时打包编译,当修改代码之后,会自动进行打包构建
2. 安装到开发依赖
cnpm i webpack-dev-server --save-dev
cnpm i webpack-cli --save-dev
3.修改package.json文件
安装完成之后,在命令行直接运行webpack-dev-server来进行打包,发现报错,此时需要借助于package.json文件中的指令,来进行运行`webpack-dev-server`命令,在scripts节点下新增"dev": "webpack-dev-server"指令,发现可以进行实时打包,但是dist目录下并没有生成`bundle.js`文件,这是因为`webpack-dev-server`将打包好的文件放在了内存中
把`bundle.js`放在内存中的好处是:由于需要实时打包编译,所以放在内存中速度会非常快
这个时候访问webpack-dev-server启动的http://localhost:8080/网站,发现是一个文件夹的面板,需要点击到src目录下,才能打开我们的index首页,此时引用不到bundle.js文件,需要修改index.html中script的src属性为:<script src="../bundle.js"></script>
为了能在访问http://localhost:8080/的时候直接访问到index首页,可以使用--contentBase src指令来修改dev指令,指定启动的根目录:
"dev": "webpack-dev-server --contentBase src"
4. 同时修改index页面中script的src属性为<script src="../dict/bundle.js"></script>
5.package.json文件内容
{ "name": "test2", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1", "dev": "webpack-dev-server --contentBase src", //"dev": "webpack-dev-server" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "webpack": "^4.35.2", "webpack-cli": "^3.3.5", "webpack-dev-server": "^3.7.2" }, "dependencies": { "jquery": "^3.4.1" } }
6.使用webpack-dev-server启动项目(我使用不是全局安装)
F: est2 ode_modules.binwebpack-dev-server
六、使用html-webpack-plugin插件配置启动页面
由于使--contentBase指令的过程比较繁琐,需要指定启动的目录,同时还需要修改index.html中script标签的src属性,所以推荐大家使用html-webpack-plugin插件配置启动页面
1. 运行cnpm i html-webpack-plugin --save-dev安装到开发依赖
2. 修改webpack.config.js配置文件如下
// 导入处理路径的模块 var path = require('path'); // 导入自动生成HTMl文件的插件 var htmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: path.resolve(__dirname, 'src/js/main.js'), // 项目入口文件 output: { // 配置输出选项 path: path.resolve(__dirname, 'dist'), // 配置输出的路径 filename: 'bundle.js' // 配置输出的文件名 }, plugins:[ // 添加plugins节点配置插件 new htmlWebpackPlugin({ template:path.resolve(__dirname, 'src/index.html'),//模板路径 filename:'index.html'//自动生成的HTML文件的名称 }) ] }
3. 修改package.json中script节点中的dev指令如下
"dev": "webpack-dev-server"
4. 将index.html中script标签注释掉,因为`html-webpack-plugin`插件会自动把bundle.js注入到index.html页面中
(1).修改webpack.config.js文件,新增devServer节点如下
其中--open表示自动打开浏览器,--port 4444表示打开的端口号为4444,--hot表示启用浏览器热更新,compress会 gzip(压缩),项目根路径下 src/ 目录的文件
devServer: { contentBase: path.join(__dirname, 'src'), compress: true, hot:true, open:true, port:4444 }
(2).在头部引入webpack模块
var webpack = require('webpack');
(3). 在plugins节点下新增
new webpack.HotModuleReplacementPlugin()
(4).查看webpack.config.js文件
// 导入处理路径的模块 var path = require('path'); // 导入自动生成HTMl文件的插件 var htmlWebpackPlugin = require('html-webpack-plugin'); // 启用热更新的 第2步 const webpack = require('webpack') module.exports = { entry: path.resolve(__dirname, 'src/js/main.js'), // 项目入口文件 output: { // 配置输出选项 path: path.resolve(__dirname, 'dist'), // 配置输出的路径 filename: 'bundle.js' // 配置输出的文件名 }, plugins:[ // 添加plugins节点配置插件 new webpack.HotModuleReplacementPlugin(), // new 一个热更新的 模块对象, 这是 启用热更新的第 3 步 new htmlWebpackPlugin({ template:path.resolve(__dirname, 'src/index.html'),//模板路径 filename:'index.html'//自动生成的HTML文件的名称 }) ], devServer: { contentBase: path.join(__dirname, 'src'), compress: true, hot:true, open:true, port:4444 }, }
七、使用webpack打包css文件
1、在src目录下创建css目录与css文件(index.css)
li{ list-style: none; }
2、运行cnpm i style-loader css-loader --save-dev
cnpm i style-loader css-loader --save-dev
3、在webpack.config.js中添加处理sass文件的loader模块
(注意:use表示使用哪些模块来处理test所匹配到的文件;use中相关loader模块的调用顺序是从后向前调用的)
module: { // 用来配置第三方loader模块的 rules: [ // 文件的匹配规则 { test: /.css$/, use: ['style-loader', 'css-loader'] }//处理css文件的规则 ] }
4、在main.js文件中引入css
import '../css/index.css'
八、使用webpack打包less文件
1. 运行cnpm i less-loader less -D
cnpm i less-loader less -D
2.在css目录下新增index.less文件
ul{ padding: 0; margin: 0; }
3. 修改webpack.config.js这个配置文件module添加(和css类似)
{ test: /.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }
4.在main.js文件中引入less
import '../css/index.less'
九、使用webpack打包sass文件
1. 运行cnpm i sass-loader node-sass --save-dev
cnpm i sass-loader node-sass --save-dev
2.在css目录下新增index.sass文件
html, body{ margin: 0; padding: 0; li{ font-size: 12px; line-height: 30px; } }
3. 在webpack.config.js中添加处理sass文件的loader模块(和css类似)
{ test: /.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }
4.在main.js文件中引入sass
import '../css/index.scss'
十、使用webpack处理css中的路径
1. 运行cnpm i url-loader file-loader --save-dev
cnpm i url-loader file-loader --save-dev
2. 在webpack.config.js中添加处理url路径的loader模块
{ test: /.(png|jpg|gif)$/, use: 'url-loader' }
3. 可以通过`limit`指定进行base64编码的图片大小;只有小于指定字节(byte)的图片才会进行base64编码
{ test: /.(png|jpg|gif)$/, use: 'url-loader?limit=43960' },
十一、使用babel处理高级JS语法
1. 运行cnpm i babel-core babel-loader babel-plugin-transform-runtime --save-dev安装babel的相关loader包
cnpm i babel-core babel-loader babel-plugin-transform-runtime --save-dev
2. 运行cnpm i babel-preset-es2015 babel-preset-stage-0 --save-dev安装babel转换的语法
cnpm i babel-preset-es2015 babel-preset-stage-0 --save-dev
3. 在webpack.config.js中添加相关loader模块,其中需要注意的是,一定要把node_modules文件夹添加到排除项
{ test: /.js$/, use: 'babel-loader', exclude: /node_modules/ }
4. 在项目根目录中添加`.babelrc`文件,并修改这个配置文件如下
{ "presets":["es2015", "stage-0"], "plugins":["transform-runtime"] }
5.注意:语法插件babel-preset-es2015可以更新为babel-preset-env,它包含了所有的ES相关的语法
十二、实验完成后的文件和目录
1.目录结构
2.文件内容
// 导入处理路径的模块 var path = require('path'); // 导入自动生成HTMl文件的插件 var htmlWebpackPlugin = require('html-webpack-plugin'); // 启用热更新的 第2步 const webpack = require('webpack') module.exports = { entry: path.resolve(__dirname, 'src/js/main.js'), // 项目入口文件 output: { // 配置输出选项 path: path.resolve(__dirname, 'dist'), // 配置输出的路径 filename: 'bundle.js' // 配置输出的文件名 }, plugins:[ // 添加plugins节点配置插件 new webpack.HotModuleReplacementPlugin(), // new 一个热更新的 模块对象, 这是 启用热更新的第 3 步 new htmlWebpackPlugin({ template:path.resolve(__dirname, 'src/index.html'),//模板路径 filename:'index.html'//自动生成的HTML文件的名称 }) ], devServer: { contentBase: path.join(__dirname, 'src'), compress: true, hot:true, open:true, port:4444 }, module: { // 用来配置第三方loader模块的 rules: [ // 文件的匹配规则 { test: /.css$/, use: ['style-loader', 'css-loader'] },//处理css文件的规则 { test: /.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }, //配置处理 .less 文件的第三方 loader 规则 { test: /.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }, // 配置处理 .scss 文件的 第三方 loader 规则 ] } }
{ "name": "test2", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo "Error: no test specified" && exit 1", "dev": "webpack-dev-server" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "css-loader": "^3.0.0", "file-loader": "^4.0.0", "html-webpack-plugin": "^3.2.0", "less": "^3.9.0", "less-loader": "^5.0.0", "node-sass": "^4.12.0", "sass-loader": "^7.1.0", "style-loader": "^0.23.1", "url-loader": "^2.0.1", "webpack": "^4.35.2", "webpack-cli": "^3.3.5", "webpack-dev-server": "^3.7.2" }, "dependencies": { "jquery": "^3.4.1" } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <!-- 注意: 不推荐直接在这里引用任何包和任何CSS文件 --> <!-- 因为 main 中的代码,涉及到了ES6的新语法,但是浏览器不识别 --> <!-- <script src="./main.js"></script> --> <!-- 通过 webpack 这么一个前端构建工具, 把 main.js 做了一下处理,生成了一个 bundle.js 的文件 --> <!-- <script src="../dist/bundle.js"></script> --> <!-- 注释掉script -->> <!-- <script src="../dist/bundle.js"></script> --> </head> <body> <ul> <li>这是第1个li</li> <li>这是第2个li</li> <li>这是第3个li</li> <li>这是第4个li</li> <li>这是第5个li</li> <li>这是第6个li</li> <li>这是第7个li</li> <li>这是第8个li</li> <li>这是第9个li</li> <li>这是第10个li</li> </ul> </body> </html>
// 这是 main.js 是我们项目的JS入口文件 // 1. 导入 Jquery // import *** from *** 是ES6中导入模块的方式 // 由于 ES6的代码,太高级了,浏览器解析不了,所以,这一行执行会报错 import $ from 'jquery' // const $ = require('jquery') // 使用 import 语法,导入 CSS样式表 import '../css/index.css' import '../css/index.less' import '../css/index.scss' // 注意: webpack, 默认只能打包处理 JS 类型的文件,无法处理 其它的非 JS 类型的文件; // 如果要处理 非JS类型的文件,我们需要手动安装一些 合适 第三方 loader 加载器; // 1. 如果想要打包处理 css 文件,需要安装 cnpm i style-loader css-loader -D // 2. 打开 webpack.config.js 这个配置文件,在 里面,新增一个 配置节点,叫做 module, 它是一个对象;在 这个 module 对象身上,有个 rules 属性,这个 rules 属性是个 数组;这个数组中,存放了,所有第三方文件的 匹配和 处理规则; // 注意: webpack 处理第三方文件类型的过程: // 1. 发现这个 要处理的文件不是JS文件,然后就去 配置文件中,查找有没有对应的第三方 loader 规则 // 2. 如果能找到对应的规则, 就会调用 对应的 loader 处理 这种文件类型; // 3. 在调用loader 的时候,是从后往前调用的; // 4. 当最后的一个 loader 调用完毕,会把 处理的结果,直接交给 webpack 进行 打包合并,最终输出到 bundle.js 中去 $(function () { $('li:odd').css('backgroundColor', 'yellow') $('li:even').css('backgroundColor', function () { return '#' + 'D97634' }) })
li{ list-style: none; }
ul{ padding: 0; margin: 0; }
html, body{ margin: 0; padding: 0; li{ font-size: 12px; line-height: 30px; } }