初识webpack4.0-基础原理

前言

以前都是使用,没有系统的完整的好好学习过一遍webpack的原理,趁如今工做有些闲空,整理下。增强下记忆

什么是webpack?

不想放webpack官网那张图,感受都快看吐了。
算了仍是妥协把,要否则很差说清楚.....
image
官网的哈,看能看出的来,那继续了~~css

分为三个部分

左侧:html

写项目的源代码,源文件
左侧有一个入口,最上面的 .js
一个一个的方格能够理解成一个一个的模块,由于webpack是基于node的,因此能够用模块的概念来区分文件。
箭头的表示➡️一个模块能够依赖多个模块
箭头➡️表示他们之间的依赖关系
左侧会有不少,后缀的文件是浏览器没法识别的。例如: .sass .hbs .cjs
因此须要通过webpack 来构建一次打包

通过webpack的构建node

右侧:webpack

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

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

webpack安装

分为两种安装方式npm

  • 项目安装(推荐)
    有些项目可能很老,依赖的webpack的版本比较低。
    最新的是webpack4.X; webpack5.x尚未发布
  • 全局安装
    若是是全局安装,版本会固定化。若是是去修改来的版本会冲突,依赖冲突等。因此根据项目来安装webpack,会好些。

安装:
webpacl4.x以后,这两个必需要都安装,webpack和 webpack-cli;不建议分开装。json

建立项目以后,现须要npm init一下,以后在安装。初始化一下。这个你们应该都知道。浏览器

npm install webpack webpack-cli -D

webpack启动

webpack4.0发布的时候,有说,支持零配置启动。结果发现,哈哈哈哈哈哈哈哈~~~没啥用。基本用不到项目中。sass

咱们来看下零配置:
安装好webpack以后,咱们来建立一个入口文件,index.js闭包

零配置 :

默认入口: ./src/index.js
若是没有src 下面的index.js 打包是不成功的。
默认出口:输出的目录是 ./dist,输出的资源名称:main.js

image
接下来,启动webpack,启动方式有两种。

第一种启动方式:

npx webpack

为啥用npx启动项目

npm5.2版本,就自带npx这个功能;
如今咱们启动的整个项目webpack是局部安装的
若是全局没有安装webpack,全局执行 webpack 就会报错, command not found。它会去全局环境变量中去寻找。
经过npx 启动webpack,它会在当前项目下的 node_modules/.bin 目录去找它的软链接,在 .bin 目录下找到webpack,去启动它。

image

来看下,打包好里面都显示了啥?

  • 构建的哈希版本
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
image
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

image

目录新建立了一个build;main.js中的文件没有被压缩,开发模式下,文件不会被打包。

image

main.js 文件内容分析

main中是一个自执行的闭包函数
//行参 modules 全部的模块
(funcition(){modules})()
image

等下,我在建立个依赖js。为了方便看这个modules里面的内容。
image

image

modules是什么?

//modules 是一个对象,这个对象记录了,从入口模块出发,以及依赖模块的信息

image

来看下,在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"
}

image
执行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'
}

image

一个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

看一下打包结果
image
没有报错 也没有显示,由于:
css-loader 的做用很是的单一,只是让咱们的webpack知道了,如何去处理css的语法,如何让css语法以字符串的方式,放到bundle文件里面去。
image

不然就会报错,接下来要作的是,将这段代码提取出来放到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;这样能够看到效果
image
浏览器打开这个index.html
image
展现成功~~~~~!耶✌️
  • 结论:
    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

image

  • 配置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

效果以下:
image
这样就打包成功了,那么直接用浏览器打开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']
       }
   ]
},

image

基本原理就差很少顺明白了。总结下


总结

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的使用,用多了就写的顺了,因此主要的仍是基础概念要清楚,因此才单独拿出来进行一个梳理,鄙人看法哈。

相关文章
相关标签/搜索