前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >10. vue之webpack打包原理和用法详解

10. vue之webpack打包原理和用法详解

作者头像
用户7798898
发布2021-03-05 12:08:59
4.7K0
发布2021-03-05 12:08:59
举报
文章被收录于专栏:盛开在夏天的太阳

一、什么是webpack

webpack官网给出的定义是

代码语言:javascript
复制
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,
它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

如上图: 中间的蓝色块就是webpack. 他会将左边各种文件打包成右侧html能够解析的文件.

总结:

代码语言:javascript
复制
webpack是一个静态的打包模块. 
这里涉及两个概念: 打包和模块

1. 什么是模块?

上一篇文章, 说了什么是模块化, 详见: https://cloud.tencent.com/developer/article/1797937

代码语言:txt
复制
模块化有很多规范, commonJs规范, AMD规范, CMD规范, ES6规范等
代码语言:txt
复制
在ES6之前, 要想使用模块化开发,就要借助其他的工具, 而且开发完成以后, 还需要处理各种依赖,并将其进行整合打包.
代码语言:txt
复制
webpack可以让我们进行模块化开发, 他提供了平台, 并且会帮助我们处理各模块之间的依赖关系.
代码语言:txt
复制
webpack最终会帮我们将js, css, 图片, json文件等打包为合适的格式, 以供浏览器使用.
代码语言:txt
复制
在webpack中上述文件类型都可以被当做模块来使用.

2. 什么是打包?

代码语言:javascript
复制
就是将webpack中各种模块资源进行打包合并成一个或多个包. 并且在打包的过程中, 可以对资源进行处理, 如:压缩图片, 将scss转成css, 将ES6语法转成ES5等可以被html识别的文件类型.

二. webpack打包工具的安装

webpack打包工具依赖nodejs. nodejs环境依赖各种包, 这些包使用npm进行管理. npm是什么呢? npm就是用来管理node下的各种包的

接下来看看webpack如何安装?

第一步: 安装nodejs

在官网下载nodejs:https://nodejs.org/zh-cn/ 安装好以后可以查看nodejs的版本

代码语言:javascript
复制
node -v

我当前的版本是 v12.16.2

默认安装nodejs的时候, 就会自动安装npm, 所以, npm不用单独安装

第二步: 安装webpack

我使用的webpack版本是3.6.0, 因为我当前使用的vue的版本是2, vue2依赖的webpack版本是3.6.0

首先查看本机是否已经安装了webpack, 使用命令查询

代码语言:javascript
复制
 webpack --version

如果没有安装, 则安装全局的webpack

代码语言:javascript
复制
npm install webpack@3.6.0 -g

-g:表示的是global  全局的意思

webpack需要全局安装, 也需要局部安装.

我们在终端或者IDE的terminal中使用webpack都是使用的全局的webpack,当我们在项目下使用package.json scripts webpacks, 这时候使用的是局部安装的.

那什么是全局webpack ,什么是本地webpack呢?

我们通常都会安装两个webpack, 一个是全局的一个是本地的.

全局的指的是电脑上安装的webpack包, 所有项目都可以使用

本地webpack是指当前项目的webpack包. 通常全局webpack版本会比较高, 而我的项目是老项目, 使用的是老版本的

webpack打包的, 这时如果使用全局的webpack打包就会报错, 所以, 需要安装一个和项目匹配的本地的webpack包

在这里, 我们先值安装全局的, 后面使用到本地的了, 再来安装本地的webpack.

三. webpack的基本使用

webpack下通常包含两个文件夹, 一个是src, 一个是dist

  • src下都会有一个main.js, 作为主js文件.
  • dist存放打包后的文件

在webpack中,我们会使用两种类型的模板来定义: 分别是commonJs语法, 和ES6语法.

  • 在main.js引用mathUtil.js, 使用commonjs语法
  • 在main.js引用dataUtil.js, 使用ES6语法

下面, 我们创建一个mathUtil.js 和 dataUtil.js两个js文件, 分别使用commonJs语法和ES6语法来创建.

    • 在main.js引用mathUtil.js, 使用commonJs语法
    • 在main.js引用dataUtil.js, 使用ES6语法

项目结构如下:

1) 使用commonJs语法

第一步: 在mathUtil.js中export, 使用commonJs模块的写法 : module.exports ={add, sub}

代码语言:javascript
复制
function add(num1, num2) {
    return num1 + num2
}


function sub(num1, num2) {
    return num1 - num2
}

// 使用commonJs导出模块
module.exports={add, sub}

这里使用的是commonJs的语法导出方法

第二步: 在main.js中引用mathUtil.js中导出的变量 const {add, sub} = require("文件名")

代码语言:javascript
复制
const{add, sub} = require("./mathUtil.js")

console.log(add(10, 20))
console.log(sub(20, 10))

第三步: 使用webpack语句打包 : webpack ./src/main.js ./dist/bundle.js

首先进入到当前项目的根目录下, 然后输入命令

代码语言:javascript
复制
webpack ./src/main.js ./dist/bundle.js

意思是: 将src目录下的main.js进行打包, 打包好的文件放在dist目录下, 并命名为bundle.js

webpack是自动打包工具, 所以, 我们只需要打包main.js, 他会自动检查main.js是否引用了其他文件. 如果有自动将其打包.

打包以后, 会生成一个bundle.js.

第四步: 在index.html中引入bundle.js文件

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./dist/bundle.js" ></script>
</head>
<body>

</body>
</html>

引入以后, 就是普通的html代码了, 我们可以向访问其他html一样,访问这个页面.

2) 使用ES6语法

第一步: 在dateUtil.js中导出, 使用ES6写法: export {var1, var2}

代码语言:javascript
复制
function priceUnit(price) {
    return "$" + price.toFixed(2)
}

export {priceUnit}

第二步: 在main.js中引用dateUtil.js中导出的变量 import {var1, var2} from "文件地址"

代码语言:javascript
复制
import {priceUnit} from "./dataUtil"

console.log(priceUnit(25))

第三步: 使用webpack语句打包 : webpack ./src/main.js ./dist/bundle.js

代码语言:javascript
复制
webpack ./src/main.js ./dist/bundle.js

第四步: 在index中引用bundle.js文件

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./dist/bundle.js" ></script>
</head>
<body>

</body>
</html> 

四. webpack配置文件

1. 如何使用webpack命令直接打包

刚刚我们打包的时候, 使用的是

代码语言:javascript
复制
webpack ./src/main.js ./dist/bundle.js

那么, 如果在项目下, 可不可以直接使用webpack, 而不用每次都指定文件呢? 这样可以方便很多

当然是可以的, 我们需要在项目根目录下创建一个文件: webpack.config.js 这个名字是固定的

这个js就是要告诉我们哪里是webpack的入口, 哪个是webpack的出口

代码语言:javascript
复制
webpack.config.js

module.export={
    entry: './src/main.js',
    output: {
        path: '/dist',
        filename: '/bundle.js'
    }
}    
  • entry用来指定入口, 指定一个路径
  • output用来指定出口. 需要注意的是: 出口是一个对象, 由两部分组成: path和filename

然后我们在终端输入webpack打包. 打包会报错, 报错信息提示很明确:

代码语言:javascript
复制
The provide value "./dist" is not an absolute path!

意思是说path应该是已经绝对路径. 也就是dist的绝对路径

思考: 我们能直接写一个绝对路径么? 比如: /Users/workspace/vue-study/webpack的配置/src/main.js 这样可以么?

这样肯定不太好, 因为我一旦将文件文在其他目录下, 这个地址就变了.

webpack可以帮助我们获取当前项目的绝对路径

我们const path = require("path")来获取相对目录. 可是当前目录下没有path的包, path是node下东西, 需要通过npm init来初始化,

2. 初始化项目npm init

初始化命令

代码语言:javascript
复制
npm init

初始化完成以后, 就会创建一个叫package.json的文件

通常, 我们需要使用node的东西, 或者单独依赖node环境的话, 都会执行npm init, 生成package.json

3. 安装模块

如果package.json里面依赖其他模块, 需要使用npm install的安装一下, 然后就会在当前文件夹中安装一些东西

代码语言:javascript
复制
npm install
  • const path = require("path")这里的path就是node给我们生成的, 我们可以直接使用.

然后我们的output中path就可以这么写:

代码语言:javascript
复制
path.resovle(__dirname, "dist")
  • _dirname是一个全局变量, resolve是一个函数, 可以将两个部分的内容拼在一块, 这样生成以后就是一个绝对路径

4. 使用npm run来启动项目

下面来看一下package.json

代码语言:javascript
复制
{
  "name": "meet",
  "version": "1.0.0",
  "description": "刚刚我们打包的时候, 使用的是webpack ./src/main.js ./dist/bundle.js 那么, 如果在项目下, 可不可以直接使用webpack, 而不用每次都指定文件呢? 可以的, 我们需要在项目根目录下创建一个文件, webpack.config.js 这个名字是固定的 这个js就是要告诉我们哪个是webpac的入口, 哪个是webpack的出口 通过module.export={     entry: './src/main.js',     output: {         path: '/dist',         filename: '/bundle.js'     } } 来告诉我们入口和出口在哪里. entry用来指定入口, 指定一个路径 output用来指定出口. 出口是一个对象",
  "main": "webpack.config.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

通常我们启动项的时候会使用npm run serve启动项目, npm run build构建项目. 当执行这个命令的时候, 就会去package.json中的script标签中找build命令和serve命令.

执行npm run build让其执行webpack打包就可以在script中增加"build":"webpack"

代码语言:javascript
复制
{
  "name": "meet",
  "version": "1.0.0",
  "description": "刚刚我们打包的时候, 使用的是webpack ./src/main.js ./dist/bundle.js 那么, 如果在项目下, 可不可以直接使用webpack, 而不用每次都指定文件呢? 可以的, 我们需要在项目根目录下创建一个文件, webpack.config.js 这个名字是固定的 这个js就是要告诉我们哪个是webpac的入口, 哪个是webpack的出口 通过module.export={     entry: './src/main.js',     output: {         path: '/dist',         filename: '/bundle.js'     } } 来告诉我们入口和出口在哪里. entry用来指定入口, 指定一个路径 output用来指定出口. 出口是一个对象",
  "main": "webpack.config.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
  "author": "",
  "license": "ISC"
}

然后就可以使用npm run webpack来打包了. 但是这里打包是全局打包. 因为我们之前只安装了一个全局的webpack.

但如果项目使用的版本和全局的不一样, 怎么办呢? 我们还可以使用局部的wenpack打包.

5. 全局webpack和局部webpack有什么区别呢?

我们通常都会安装两个webpack,

  • 一个是全局的
  • 一个是本地的.

全局的指的是电脑上安装的webpack包, 所有项目都可以使用

本地webpack是指当前项目的webpack包.

通常全局webpack版本会比较高, 而我的项目是老项目, 使用的是老版本的

webpack打包的, 这时如果使用全局的webpack打包就会报错, 所以, 需要安装一个和项目匹配的本地的webpack包

6. 安装本地webpack命令

代码语言:javascript
复制
npm install webpack@3.6.0 --save-dev
  • --save-dev: 这个参数的含义表示开发时依赖.
这里有两个概念:
    1. 开发时依赖
    1. 运行时依赖

对于打包来说, 我们只有在开发环境才会打包, 开发好以后要上线了会将其构建成html代码, 放到服务器上运行,

放到服务器以后, 就不需要打包了, 所以, 打包只需要在开发时使用, 是一个开发时依赖

本地webpack安装好以后, 会在package.json中看到devDependencies属性, 这就是开发时依赖

本地webpack安装好以后, 使用npm run build进行打包. 那是使用的全局webpack打包的还是本地webpack打包的呢?

本地安装好webpack以后会多出一个文件夹node_modules, 这里是默认在本地装的包, 其中有一个是webpack, 使用这里面的webpack

就表示使用的局部webpack打包. 而当我们在终端, 或者ide的terminal中执行webpack命令都是全局的

如果想要使用局部webpack打包, 可以使用npm run build. 这时就是去package.json的script脚本中找build命令了.

package.json中脚本命令执行的顺序:

  • 首先, 在本地的路径中找命令
  • 然后, 本地没有, 再去全局中找命令

在这里首先回去本地找有没有这个命令, 如果没有就去全局找

五.使用webpack打包css文件

webpack主要是用来打包的, 我们之前都是打包了js代码文件, 那如果还有css, 图片, 或者一些高级转换,如将ES6转换成ES5,将scss, less转成css, 将.vue文件转换成js文件怎么办呢?

webpack单独是不能完成转换的,需要借助loader.

1. 什么是绍loader?

webpack 可以使用 loader 来预处理文件。这允许你打包除 JavaScript 之外的任何静态资源。

loader是webpack中一个非常核心的概念, loader有很多种, 不同的内容需要使用不同的loader来加载.

2. loader的使用

我们首先来创建一个css文件, 然后将css文件引入到项目中

第一步: 创建main.css文件

代码语言:javascript
复制
body{
    background-color: #085e7d;
}

第二步: 将main.css文件引入到main.js中

代码语言:javascript
复制
require("./css/main.css")

这是使用commonJs的写法引入的. 引入css以后, 不需要任何返回值, 所以, 我们可以不用写成 "let 变量名 = require(文件路径)"

第三步: 执行npm run build, 会报异常

这个异常的意思是, 缺少合适的loader. 因为我们引入了css, 但是还没有引入解析css的loader.

css需要两个loader :

  • 一个是css-loader
  • 另一个是style-loader

css-loader: 只负责加载css文件, style-loader: 负责将样式加载到Dom中

第四步: 通过npm安装loader

我们的目标是安装loader, 可以去官网找到对应的loader. css文件对应的loader.

官网地址: www.webpackjs.com

找到css-loader的用法

安装命令

代码语言:javascript
复制
npm install --save-dev css-loader 

第五步: 在webpack.config.js中的modules关键字下配置

代码语言:javascript
复制
  module: {
        rules: [    
            {
                test: /\.css$/,
                use: ['css-loader']
            }

        ]
    }

第六步: 安装style-loader

安装方法和css是一样的. 可以通过查询官网找到方法

安装style-loader命令

代码语言:javascript
复制
npm install --save-dev style-loader    

然后在将style-loader放在css-loader的前面

代码语言:javascript
复制
module: {
    rules: [
        {
            test: /\.css$/,
            // css-loader: 只负责加载css文件
            // style-loader: 负责将样式加载到Dom中
            // 注意: 使用loader加载的时候, 是从右向左加载的. 所以, 先加载css-loader, 在加载style-loader
            use: ['style-loader','css-loader' ]
        }

    ]
}

为什么需要将style-loader放在前面呢?

其实在解析css的过程中, 先用到的是css-loader, 然后使用到的是style-loader. 但是webpack.config.js在解析的时候, 是从右往左解析的.

第七步: 打包

代码语言:javascript
复制
npm run build

打包以后报错:

代码语言:javascript
复制
css (node:93638) UnhandledPromiseRejectionWarning: TypeError: this.getResolve is not a function

遇到这个问题, 说明版本不合适, 我们使用的webpack是3.6.0的版本, 打包的时候, 我们需要重新制定一下css-loader和style-loader的版本号

打开package.json, 找到devDependencies

代码语言:javascript
复制
"devDependencies": {
    "css-loader": "^2.1.1",
    "style-loader": "^2.0.0",
    "webpack": "^3.6.0",
  }

指定css-loader和style-loader的版本号分别是2.1.1和2.0.0

再次打包, 成功!

六. webpack打包less文件

其实我们知道如何打包css文件了, 那么打包less文件方法是类似的

第一步: 定义一个less文件

我们定义一个less文件, 起个名字common.less

代码语言:javascript
复制
@fontsize: 24px;
@fontcolor: #5112b8;

body {
  font-size: @fontsize;
  color: @fontcolor;
}

第二步: 将less文件import引入到main.js中

代码语言:javascript
复制
require("./css/special.less")

第三步: 安装less组件, 应该安装哪些组件呢? 可以看https://cn.vuejs.org/v2/guide/

查询官网: www.webpackjs.com

安装组件命令

代码语言:javascript
复制
npm install --save-dev less-loader less

添加规则

代码语言:javascript
复制
module.exports = {
    ...
    module: {
        rules: [{
            test: /\.less$/,
            use: [{
                loader: "style-loader" // creates style nodes from JS strings
            }, {
                loader: "css-loader" // translates CSS into CommonJS
            }, {
                loader: "less-loader" // compiles Less to CSS
            }]
        }]
    }
};

注意: 顺序不能改变

第四步: 重新打包.

代码语言:javascript
复制
npm run build

七. webpack打包图片文件

下面来看看webapck是如何打包图片的

第一步: 在css中引入一个图片文件

比如: 我引入了一个背景图

然后将图片作为背景引入到main.css中

代码语言:javascript
复制
body{
    background: url("../img/123.jpeg");
}

第二步: 将main.css文件通过import引入到main.js中

代码语言:javascript
复制
require("./css/main.less")

我们知道webpack是自动打包工具, 在打包main.js的时候, 他会看里面都引入了哪些内容. 他发现引入了main.css, 就是去自动加载并解析css对应的模块. 在css中引入了图片, 就会去自动加载并解析图片对应的模块.

第三步: 安装解析图片的组件

查询官网: www.webpackjs.com

我们看到background是通过url引入的, 首先需要url-loader模块.

安装组件命令

代码语言:javascript
复制
npm install --save-dev url-loader 

添加规则

代码语言:javascript
复制
{
    test: /\.(png|jpg|gif|jpeg)$/,
    use: [ {
        loader: 'url-loader',
        options: {
            limit: 8000,
        }
    }]
}

我们发现这次引入的时候有一个options参数, 这个参数限制了图片的大小.

注意:

  • 当加载的图片, 小于limit时, 会将图片编译成base64字符串形式. --- 不需要文件, 因为他是一个base64字符串
  • 当加载的图片, 大于limit是, 需要使用file-loader模块来加载. --- 当文件来处理, 就需要打包成文件, 需要file-loader

当以文件的形式加载的时候, 需要指定一个打包路径. 否则加载的文件目录是根目录, 结果会找不到文件, 因为我们的文件最终打包到dist下面了.

代码语言:javascript
复制
module.exports={
    // 入口
    entry: "./src/main.js",
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: "bundle.js",
        publicPath:"dist/"
    }
...
}

我们可以在output位置增加publicPath:"dist/" 以后, 所有的路径类的文件在打包编译的时候, 都会打包到这个路径下面

八. webpack打包--将ES6打包成ES5

为什么需要将es6打包成es5呢? 因为上述方式的webpack打包后, 并没有将ES6的语法转换成ES5的, 比如:

这会有什么问题呢?

有些浏览器可能不认识. 因为不是所有的浏览器都兼容ES6, 但基本所有的浏览器都兼容ES5的语法. 因此我们需要将ES6的语法转换成ES5的语法

方法和上面是一样的.

第一步: 安装组件

打包ES6到ES5需要的组件是bebal

查询官网需要安装哪些组件: www.webpackjs.com

安装命令:

代码语言:javascript
复制
npm install --save-dev babel-loader@7 babel-core babel-preset-es2015

我们这里安装的是babel-loader的7的版本. babel-preset的版本是es2015

第二步: 配置babel-loader组件

代码语言:javascript
复制
module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /(node_modules|bower_components)/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['es2015']
        }
      }
    }
  ]
}

这个配置里面指定了exclude, 排除哪些目录: 这里排除了node_modules目录, 因为这个目录下的文件我们不需要打包. 是node编译需要的内容.

presets属性,用来指定将es6转换成es5需要的版本. 我们这里直接填es2015就可以了.

第三步: 打包

代码语言:javascript
复制
npm run build

这次在去看bundle.js文件, 里面就没有es6的语法了

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-03-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、什么是webpack
    • 1. 什么是模块?
      • 2. 什么是打包?
      • 二. webpack打包工具的安装
        • 第一步: 安装nodejs
          • 第二步: 安装webpack
            • webpack需要全局安装, 也需要局部安装.
            • 那什么是全局webpack ,什么是本地webpack呢?
        • 三. webpack的基本使用
          • 1) 使用commonJs语法
            • 第一步: 在mathUtil.js中export, 使用commonJs模块的写法 : module.exports ={add, sub}
            • 第三步: 使用webpack语句打包 : webpack ./src/main.js ./dist/bundle.js
            • 第四步: 在index.html中引入bundle.js文件
          • 2) 使用ES6语法
            • 第一步: 在dateUtil.js中导出, 使用ES6写法: export {var1, var2}
            • 第二步: 在main.js中引用dateUtil.js中导出的变量 import {var1, var2} from "文件地址"
            • 第四步: 在index中引用bundle.js文件
        • 四. webpack配置文件
          • 1. 如何使用webpack命令直接打包
            • 2. 初始化项目npm init
              • 3. 安装模块
                • 4. 使用npm run来启动项目
                  • 5. 全局webpack和局部webpack有什么区别呢?
                    • 6. 安装本地webpack命令
                      • package.json中脚本命令执行的顺序:
                  • 五.使用webpack打包css文件
                    • 1. 什么是绍loader?
                      • 2. loader的使用
                        • 第一步: 创建main.css文件
                        • 第二步: 将main.css文件引入到main.js中
                        • 第三步: 执行npm run build, 会报异常
                        • 第四步: 通过npm安装loader
                        • 第五步: 在webpack.config.js中的modules关键字下配置
                        • 第六步: 安装style-loader
                    • 六. webpack打包less文件
                      • 第一步: 定义一个less文件
                        • 第二步: 将less文件import引入到main.js中
                          • 第三步: 安装less组件, 应该安装哪些组件呢? 可以看https://cn.vuejs.org/v2/guide/
                          • 七. webpack打包图片文件
                            • 第一步: 在css中引入一个图片文件
                              • 第二步: 将main.css文件通过import引入到main.js中
                                • 第三步: 安装解析图片的组件
                                  • 这会有什么问题呢?
                              • 八. webpack打包--将ES6打包成ES5
                                • 第一步: 安装组件
                                  • 第二步: 配置babel-loader组件
                                    • 第三步: 打包
                                    相关产品与服务
                                    云服务器
                                    云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
                                    领券
                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档