乐趣区

关于webpack:初识webpack40基础原理

前言

之前都是应用,没有零碎的残缺的好好学习过一遍 webpack 的原理,趁现在工作有些闲空,整顿下。增强下记忆

什么是 webpack?

不想放 webpack 官网那张图,感觉都快看吐了。
算了还是斗争把,要不然不好说分明 …..

官网的哈,看能看出的来,那持续了~~

分为三个局部

左侧:

写我的项目的源代码,源文件
左侧有一个入口,最下面的 .js
一个一个的方格能够了解成一个一个的模块,因为 webpack 是基于 node 的,所以能够用模块的概念来辨别文件。
箭头的示意 ➡️一个模块能够依赖多个模块
箭头➡️示意他们之间的依赖关系
左侧会有很多,后缀的文件是浏览器无奈辨认的。例如:.sass .hbs .cjs
所以须要通过 webpack 来构建一次打包

通过 webpack 的构建

右侧:

输入浏览器能够正确执行的文件,资源

咱们还能够利用 webpack 来压缩 js、压缩图片。
所以 webpack 就是一个模块打包器

webpack 装置

分为两种装置形式

  • 我的项目装置 (举荐)
    有些我的项目可能很老,依赖的 webpack 的版本比拟低。
    最新的是 webpack4.X;webpack5.x 还没有公布
  • 全局装置
    如果是全局装置,版本会固定化。如果是去批改来的版本会抵触,依赖抵触等。所以依据我的项目来装置 webpack,会好些。

装置:
webpacl4.x 之后,这两个必须要都装置,webpack 和 webpack-cli;不倡议离开装。

创立我的项目之后,现须要 npm init 一下,之后在装置。初始化一下。这个大家应该都晓得。

npm install webpack webpack-cli -D

webpack 启动

webpack4.0 公布的时候,有说,反对零配置启动。后果发现,哈哈哈哈哈哈哈哈~~~没啥用。根本用不到我的项目中。

咱们来看下零配置:
装置好 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

  • 执行构建的 webpack 版本

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 配置文件,自定义配置文件

在根目录下创立,webpack.config.js
webpack.config.js 就是 webpack 的自定义配置文件
当咱们执行 npx webpack
首先会去我的项目上来查找 是否有 webpack.config.js, 这个配置文件;如果没有会走默认配置;如果存在,就会依照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.js 文件内容分析

main 中是一个自执行的闭包函数

// 行参 modules 所有的模块
(funcition(){modules})()

等下,我在创立个依赖 js。为了不便看这个 modules 外面的内容。

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 进行打包

webpack 外围概念

  • enrty:webpack 执行构建的入口,默认是./src/index.js;

看官网那个图,就能看进去,须要一个 js 文件入口。当然这个文件入口也是能够批改的。
创立一个 webpack.config.js,entry 就能够进行批改。

  • output: 配置资源输入的地位和名称,

打包好的文件放在什么地位,叫什么名字

  • mode:打包构建模式,有开发模式和生产模式两种。

development: 开发模式,不压缩代码,有利于查找谬误
productiont:生产模式,公布到线上的代码,代码会被压缩

  • chunk:代码片段,由入口模块文件与依赖模块的内容生成的。
  • module:模块,webpack 基于 nodeJs,有所有皆模块的概念

在刚刚咱们打包的 a.js or index.js ; 或者前面会去增加的 index.css, 图片等,都能够成为模块

bundle:打包输入到资源目录的文件,构建胜利后的输入文件

顺一顺~~~~
bundle chunk module, 三者的关系:

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**

  • loader:模块转换;webpack 默认只反对 js 模块,json 模块。

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.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',
 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 -D

style-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”]

  • plugin:webpack 的一个性能扩大

举例:像咱们刚刚手动去创立的 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 的配置文件

  1. 引入 plugin
plugins:[
   new miniCssExtractPlugin({filename:'css/index.css'})
]
  1. 批改 css 文件的模块匹配规定和渲染形式
module:{
   rules:[
       {
           test:/.css$/,
           use:[miniCssExtractPlugin.loader,'css-loader']
       }
   ]
},

基本原理就差不多顺明确了。总结下


总结

webpack.config.js: webpack 配置文件

基本概念

  • entry:webpack 执行构建工作的入口文件
  • output:执行构建后,资源配置的输入地位和名称
  • module:模块
  • chunk:入口文件和依赖模块组合,通过 webpack 构建成生的一段代码片段
  • bundle:webpack 构建实现够后输入的文件
  • loader:模块转化,让 webpack 能够反对转化更多的模块类型
  • plugin:插件,让 webpack 性能更弱小
  • modle:打包构建模式,开发模式 or 生产模式

外围配置

  • enrty:String|[]|{}

[] : 单页面利用
{}: 能够 SPA or MPA。多入口对应多进口文件

  • output:{path:,filename:“”}

path: 必须是绝对路径
filename 能够应用占位符 [name] [hash] 等

  • mode:String

参数:“production”“development”“node”

  • module :{}

{rules:[]}

  • plugins : []
    • *

webpack 的学习,其实就是各种 plugin 和 module 的应用,用多了就写的顺了,所以次要的还是根底概念要分明,所以才独自拿进去进行一个梳理,鄙人见解哈。

退出移动版