以前都是使用,没有系统的完整的好好学习过一遍webpack的原理,趁如今工做有些闲空,整理下。增强下记忆
不想放webpack官网那张图,感受都快看吐了。
算了仍是妥协把,要否则很差说清楚.....
官网的哈,看能看出的来,那继续了~~css
左侧:html
写项目的源代码,源文件
左侧有一个入口,最上面的.js
一个一个的方格能够理解成一个一个的模块,由于webpack是基于node的,因此能够用模块的概念来区分文件。
箭头的表示
➡️一个模块能够依赖多个模块
箭头➡️表示他们之间的依赖关系
左侧会有不少,后缀的文件是浏览器没法识别的。例如:.sass .hbs .cjs
因此须要通过webpack 来构建一次打包
通过webpack的构建node
右侧:webpack
输出浏览器能够正确执行的文件,资源
咱们还能够利用webpack来压缩 js 、压缩图片 。
因此webpack就是一个模块打包器web
分为两种安装方式npm
(推荐)
最新的是webpack4.X; webpack5.x尚未发布
安装:
webpacl4.x以后,这两个必需要都安装,webpack和 webpack-cli;不建议分开装。json
建立项目以后,现须要npm init
一下,以后在安装。初始化一下。这个你们应该都知道。浏览器
npm install webpack webpack-cli -D
webpack4.0发布的时候,有说,支持零配置启动。结果发现,哈哈哈哈哈哈哈哈~~~没啥用。基本用不到项目中。sass
咱们来看下零配置:
安装好webpack以后,咱们来建立一个入口文件,index.js
闭包
零配置 :
默认入口:./src/index.js
若是没有src 下面的index.js 打包是不成功的。
默认出口:输出的目录是./dist
,输出的资源名称:main.js
接下来,启动webpack,启动方式有两种。
npx webpack
为啥用npx启动项目
npm5.2版本,就自带npx这个功能;
如今咱们启动的整个项目webpack是局部安装的
若是全局没有安装webpack,全局执行webpack
就会报错,command not found
。它会去全局环境变量中去寻找。
经过npx 启动webpack,它会在当前项目下的node_modules/.bin
目录去找它的软链接,在.bin
目录下找到webpack,去启动它。
来看下,打包好里面都显示了啥?
Hash: 096bb4bcb72f81514554
Version: webpack 4.44.1
Time: 217ms
// 输出的资源叫main.js
// 这个资源是958 bytes
// Chunks 是为 0
Built at: 2020-08-25 14:45:08 Asset Size Chunks Chunk Names main.js 958 bytes 0 [emitted] main // 这块表示 输出的main.js,是根据./src/index.js文件built而来的 Entrypoint main = main.js [0] ./src/index.js 29 bytes {0} [built]
本身百度吧,好吗? 用我小学的英语水平大概就是:环境没有设置:就是生产环境和开发环境没设置。会走一个默认的值,默认值是production(生产模式);
生产模式下的代码是进行压缩的,如今能够看下,main.js
![]()
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/configuration/mode/
测试打包好的main.js;是否可使用
在dist里面,手动建立一个index.html,而后手动引入main.js;
dist/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> </head> <body> <script src="./main.js"></script> </body> </html>
在package.json,的scripts中,添加启动命令
"scripts": { "dev": "webpack" },
以后执行
npm run dev
效果和上面是同样的,就不进行在进行演示了。
当咱们在scripts中去定定义了执行命令dev,执行webpack;是从本地的
node_modules/.bin
目录的软链接去找webpack
在根目录下建立,webpack.config.js
webpack.config.js
就是webpack的自定义配置文件
当咱们执行npx webpack
首先会去项目下去查找 是否有webpack.config.js
,这个配置文件;若是没有会走默认配置;若是存在,就会按照webpack.config.js
配置里面的内容去进行构建
webpack是基于node 的,因此能够直接导出模块
module.exports={ entry(入口):(有三种类型) output(出口): { // 指定输入资源存放目录,位置 // path 必须是绝对路径 path:, //输出文件名 filename:, } // 刚刚报的警告,就是这个值没有设置。 mode: 构建模式 }
webpack.config.js
const path =require('path') module.exports={ entry:'./src/index.js', output:{ path:path.resolve(__dirname,'./build'), filename:'main.js' }, // 开发模式 mode:'development' }
npx webpack
目录新建立了一个build;main.js中的文件没有被压缩,开发模式下,文件不会被打包。
main中是一个自执行的闭包函数
//行参 modules 全部的模块 (funcition(){modules})()
等下,我在建立个依赖js。为了方便看这个modules里面的内容。
//modules 是一个对象,这个对象记录了,从入口模块出发,以及依赖模块的信息
来看下,在src/index.js中的内容
/***/ "./src/index.js": /*!**********************!*\ !*** ./src/index.js ***! \**********************/ /*! no exports provided */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _a_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./a.js */ \"./src/a.js\");\n\nconsole.log('hello webpack'+_a_js__WEBPACK_IMPORTED_MODULE_0__[\"str\"]);\n\n//# sourceURL=webpack:///./src/index.js?"); /***/ })
引入a.js的方式改成了__webpack_require_
经过webpack构建,对内容进行了一层处理,模块化语句也进行了一次处理
__webpack_require_
在自执行函数中定义了这个方法的执行。
(先简单说明下,后面会写具体的文档)
继续webpack配置文件;好比咱们在Vue cli工具建立的文件;因此咱们能够本身去定义webpack配置文件的名称,能够不叫webpack.config.js
;默认是走这个文件;
好比在根目录下新建一个,webpack.ohh.js
;那如何让webpack走这个配置文件呢,
须要在package.js
中
// --config 用这个--config来进行匹配 "scripts":{ "dev": "webpack --config ./webpack.ohh.js" }
执行npm run dev
进行打包
./src/index.js
;看官网那个图,就能看出来,须要一个js文件入口。固然这个文件入口也是能够修改的。
建立一个webpack.config.js,entry 就能够进行修改。
打包好的文件放在什么位置,叫什么名字
development:开发模式,不压缩代码,有利于查找错误
productiont:生产模式,发布到线上的代码,代码会被压缩
在刚刚咱们打包的 a.js or index.js ;或者后面会去添加的 index.css,图片等,均可以成为模块
bundle: 打包输出到资源目录的文件,构建成功后的输出文件
SPA 项目 一个单页面应用,只会有一个bundle 文件;
MPA 项目 多页面应用,就会有多页面的bundle文件;好比index.js 和login.js
上面放了不少都是跑的SPA 单页面的应用;来看一个多页面MPA的。
首先是配置:
webpack.ohh.js
const path = require('path') // 多入口 module.exports={ entry:{ index:'./src/index.js', login:'./src/login.js' }, output:{ path:path.resolve(__dirname, 'ohh'), filename:'[name].js' }, mode:'development' }
一个bundle 文件,对应一个chunk里面会有多个片断
MPA 多页面应用,才会存在多个chunks;
SPA 单页面应用,只有一个入口,一个chunk,(可是可能会有多个片断组成:好比index.js中引入了a.js;那么chunk就有两个片断:一个是index、一个是a文件;);
**一个chunk对应一个entry
一个entry对应多个module**
css模块,和图片模块都不支持。就须要用到loader,
好比:src/index.css
body{ background: pink; }src/index.js
引入 css// a.js // export const str='这是ajs'; import {str} from './a.js' import css from './index.css'; console.log('hello webpack'+str);须要去配置loader
在配置文件,固然你也能够额写在webpack.config.js中。
建立一个module,写入加载规则
webpack.ohh.jsconst path = require('path') // 多入口 module.exports={ entry:{ index:'./src/index.js', login:'./src/login.js' }, output:{ path:path.resolve(__dirname, 'ohh'), filename:'[name].js' }, mode:'development', module:{ // 模块 rules:[ // 规则 { test: /\.css$/, use: "css-loader" }, ] } }进行安装 css-loader
npm install css-loader -D以后来跑一下项目:
npm run dev看一下打包结果
没有报错 也没有显示,由于:
css-loader 的做用很是的单一,只是让咱们的webpack知道了,如何去处理css的语法,如何让css语法以字符串的方式,放到bundle文件里面去。不然就会报错,接下来要作的是,将这段代码提取出来放到html中。
npm install style-loader -Dstyle-loader 的做用:
将css提取出来,而且在html的头部,动态的生成style标签,将css放到里面去。
这时,还须要去修改下配置文件的module
webpack的配置文件修改;module:{ rules:[ { test:/\.css$/, use:["style-loader", "css-loader"] } ] }添加一个style-loader
loader的自行顺序,user:[];执行顺序是从后往前的,因此先要把css解析出来,之后再用style-loader,生成style标签,将css内容放进去。【从右到左】
- 安装完了style-loader
- 配置文件修改了css文件的匹配规则
- 执行 npm run dev,查看页面加载状况
- 在打包好的文件中,【本身 建立】建立一个index.html;这样能够看到效果
![]()
浏览器打开这个index.html
![]()
展现成功~~~~~!耶✌️
- 结论:
css-loader和style-loader须要配合来使用
- 为何css-loader功能单一,为何要配合style-loader 才生效?
由于 自定义loader规定,一个loader只作一件事情。
style-loader的功能也很单一,把样式放在一个动态生成的style标签里面。因此不会在本地打包的html文件中显示出来,是经过js动态生成的。因此引入js就能够。
若是像将css处理成单独的文件,而不是在页面建立一个style标签的形式放在html里面。那就不能用style-loader;
index.less的文件,咱们就有须要去加新的匹配规则,["style-loader","css-loader","less-loader"]
举例: 像咱们刚刚手动去建立的index.html
若是咱们想要看到效果就须要,在打包个人文件夹中去手动建立index.html;很是的繁琐,那么如何解决呢?这个时候利用plugin;至关于webpack 的一个功能扩展。【官网中-右上角导航就有plugin,找一个合适的进行使用】
接下来,以如何自动建立index.html 来进行开展plugin的使用讨论先安装:
npm install html-webpack-plugin -D
- 配置webpack默认项:
webpack.config.js
const path =require('path') // 这里导入html-webpack-plugin const htmlWebpackPlugin = require('html-webpack-plugin') // 单入口 module.exports={ entry:'./src/index.js', output:{ path:path.resolve(__dirname,'./build'), filename:'main.js' }, // 开发模式 mode:'development', module:{ rules:[ { test:/.css$/, use:['style-loader','css-loader'] } ] }, plugins:[ new htmlWebpackPlugin({ // plugin的使用,先new一下 template:'./src/index.html', // 模板文件 filename:'index.html' //倒出的文件名 }) ] }
由于是在默认文件配置,因此跑起来,须要执行
npx webpack效果以下:
这样就打包成功了,那么直接用浏览器打开index.html
就能够看到效果了。并不在截图,由于和上面那个图片展现是同样的。就换成了自动生成html而已,仅此而已。
继续~~~~~(为何要总结原理,我越写饿了,难过)为了保证每次建立出来的build,打包文件都是全新的,并且不存在冗余的文件,好比说,当咱们修改了一下 plugins中的
new htmlWebpackPlugin中的打包目录地址的配置:
filename:'html/ohh.html'
那么上次打包在根目录下的html并不会删除,就冗余了呗。
咱们就须要用到plugin来进行配置
先安装:npm install clean-webpack-plugin -D使用,都是同样的
const {CleanWebpackPlugin} = require('clean-webpack-plugin') // 在pulugins中new一 plugins:[ new htmlWebpackPlugin({ // plugin的使用,先new一下 template:'./src/index.html', // 模板文件 filename:'index.html' //倒出的文件名 }), new CleanWebpackPlugin() ]
- 引入css文件而不是写在style标签里面,把样式抽离成独立的文件
首先安装plugin
npm install mini-css-extract-plugin -D修改webpack的配置文件
- 引入plugin
plugins:[ new miniCssExtractPlugin({ filename:'css/index.css' }) ]
- 修改css文件的模块匹配规则和渲染方式
module:{ rules:[ { test:/.css$/, use:[miniCssExtractPlugin.loader,'css-loader'] } ] },
基本原理就差很少顺明白了。总结下
webpack.config.js: webpack配置文件
[] : 单页面应用
{}: 能够SPA or MPA。多入口对应多出口文件
path:必须是绝对路径
filename 可使用占位符 [name] [hash]等
参数:“production” “development” “node”
{rules:[]}
webpack的学习,其实就是各类plugin和module的使用,用多了就写的顺了,因此主要的仍是基础概念要清楚,因此才单独拿出来进行一个梳理,鄙人看法哈。