webpack学习笔记

什么是webpack

webpack是前端打包工具,能让浏览器支持模块化,自动分析项目的所有依赖关系,然后按照指定的规则生产对应的静态资源。
官网在这:https://www.webpackjs.com/

  • webpack核心主要进行 JavaScript 资源打包
  • 如下图,它可以结合其他插件工具,将多种静态资源css、png、sass 分类转换成一个个静态文件,这样可以减少页面的请求。
  • 可集成 babel 工具实现 EcmaScript 6 转 EcmaScript 5 ,解决兼容性问题
  • 可集成 http 服务器
  • 可集成模块热加载,当代码改变后自动刷新浏览器 等等功能
    在这里插入图片描述

全局安装webpack

yarn global add webpack --dev

局部安装webpack

yarn add webpack --dev

全局安装和局部安装webpack的对比

全局安装

  • 优点
    全局安装的优点在于不需要每个项目都安装webpack,方便自己开发打包
  • 缺点
    当自己的项目代码要给其他人使用时,要求他人必须安装与自己同样版本的webpack才能正常打包

局部安装

  • 优点
    webpack与项目一起,不管项目代码在哪里使用都能保证webpack版本与自己一致,打包不受影响
  • 缺点
    自己开发的时候,每个项目都要安装webpack

你们会选择哪种安装方式呢?

webpack-cli

如果是webpack4以上版本,还需要安装webpack-cli才能使用webpack命令。
安装webpack-cli的方式与webpack的安装方式要保持一致,即webpack是全局安装的,webpack-cli也要全局安装。

yarn global add webpack-cli --dev 或 yarn add webpack-cli --dev

安装成功后可以查看版本

  • 全局安装
webpack -v
> 4.41.4
  • 局部安装
项目路径\node_modules\.bin\webpack -v
> 4.41.4

由于局部安装必须要找到.bin目录才能执行webpack命令,每次输入比较麻烦,yarn提供简写方式
yarn webpack -v
可以通过一条命令一并安装这两个库,用空格隔开,-D跟–dev一个意思
yarn add webpack webpack-cli -D

webpack的小例子

创建webpack-demo项目

在vscode工作空间创建webpack-demo目录,在webpack-demo目录下执行命令

yarn init

目录结构如下

在这里插入图片描述

bar.js代码如下

// nodejs模块化编程,导出一个函数
module.exports = function(){
    console.log('我是bar模块')
}

在main.js中引用bar模块

const bar = require('./bar')

bar()

index.html中引入main.js

<!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>
    
</body>
<script src="./js/main.js"></script>
</html>

浏览器访问index.html

在这里插入图片描述

这里报错的原因是浏览器并不支持模块化编程,如果我们在项目目录下用node命令来执行main.js是可以运行的

node .\js\main.js

在这里插入图片描述

通过webpack命令打包后看看,在项目目录下执行命令

yarn webpack .\js\main.js -o .\js\bundle.js

第一个参数是源文件,第二个参数 -o 是输出的意思,第三个参数是输出文件

打包完成后js目录下会多一个bundle.js文件

在这里插入图片描述

index.html引入bundle.js文件,刷新页面,F12可以正常看到输出信息

<script src="./js/bundle.js"></script>

在这里插入图片描述

模块化目录结构规范

源代码放在src目录,打包后的文件放在dist目录

在这里插入图片描述

打包配置文件webpack.config.js

如果修改完js代码都要打包,每次打包都要指明源文件和输出文件比较麻烦,可以用webpack.config.js来解决。

创建webpack.config.js

在项目目录下创建webpack.config.js

在这里插入图片描述

webpack.config.js的配置代码如下

// 引入nodejs路径小工具
const path = require('path')

// 导出webpack配置对象
module.exports = {
    // 入口js
    entry: './src/main.js',

    // 出口配置对象
    output: {
        // path必须是绝对路径,所以这里需要引入nodejs的路径小工具来帮助我们找到当前目录的绝对路径
        // __dirname是path内置的全局变量,当前js文件所在目录的绝对路径
        path : path.join(__dirname, './dist/'),
        filename: 'bundle.js'
    },
    // 打包模式有三种,development、production、none
    mode: 'development'
}

打包模式说明

  • development 开发模式,输出的bundle.js文件不会被压缩
  • production 生产模式,默认值,输出的bundle.js会被压缩
  • none 没有模式,目测与development效果一样

再执行一次webpack命令,这次不需要任何参数

yarn webpack

命令别名

命令别名可以简化命令的输入,或者以自己容易理解的词语代替默认命令。

修改package.json

添加scripts属性

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "学习webpack用的",
  "main": "index.js",
  "author": "pjh",
  "license": "MIT",
  "devDependencies": {
    "webpack": "^4.41.4",
    "webpack-cli": "^3.3.10"
  },
  "scripts": {
    "show": "webpack -v",
    "start": "node ./src/main",
    "build": "webpack"
  }
}

尝试输入自定义命令

yarn show
yarn start
yarn build

模块化编程的ES6规范

ES5ES6说明
require()import导入模块
module.exportsexport导出成模块
export default导出默认成员,只能有一个

修改webpack-demo项目

bar.js

export default function () {
    console.log('这是bar模块')
}

main.js

import bar from './bar'

bar()

导出多个变量

bar.js

export const a = 1
export const b = 2

export function sum() {
    return a + b
}

export function decrease() {
    return a - b
}

main.js

  • 导入部分变量
import {a,b,sum} from './bar'

console.log(a)
console.log(b)
console.log(sum())
  • 导入所有变量
import * as bar from './bar'

console.log(bar.a)
console.log(bar.b)
console.log(bar.sum())
console.log(bar.decrease())

export一个变量的时候必须指定default

打包CSS/Images等资源

webpack本身只针对JS打包的,默认是不支持打包CSS/Images等资源。
webpack提供了一套loader规范,运行自行编写loader来支持各种格式资源的打包。

打包CSS资源

  1. 安装stye-loader和css-loader依赖
  • syle-loader让JS认识CSS
  • css-loader将CSS装载到JS中
yarn add style-loader css-loader -D
  1. 修改webpack.config.js
const path = require('path')

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.join(__dirname, './dist/'),
        filename: 'bundle.js'
    },
    // 模式有三种,development、production、none
    mode: 'none',

    module: {// 模块设置
        rules: [// 打包规则
            {
                test: /\.css$/, // 匹配css文件
                use: [// 使用loader,顺序不能错
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }
}
  1. 创建style.css文件
    在src目录下创建创建css/style.css文件
body {
    background-color: red;
}
  1. 在main.js中引入css文件
import '../css/style.css'
  1. 重新打包项目看效果
yarn build

原理是打包时把style.css文件加载到JS中,在浏览器执行的时候会实行这段JS代码,动态添加style标签给body添加样式

打包Images资源

  1. 安装file-loader
yarn add file-loader -D
  1. 修改webpack.config.js
const path = require('path')

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.join(__dirname, './dist/'),
        filename: 'bundle.js'
    },
    // 模式有三种,development、production、none
    mode: 'none',

    module: {// 模块设置
        rules: [// 打包规则
            {
                test: /\.css$/, // 匹配css文件
                use: [// 使用loader,顺序不能错
                    'style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.(bmp|png|jpg|gif|svg)$/, // 匹配图片
                use: [// 使用loader
                    'file-loader'
                ]
            }
        ]
    }
}
  1. 在src目录下创建images目录,放入一张图片

在这里插入图片描述

  1. 修改style.css
body {
    background-color: red;
    background-image: url("../images/background.bmp");
}
  1. 重新打包
yarn build

打包后刷新页面发现图片未显示,原因时index.html访问图片路径为根目录,而打包后图片放在了/dist目录下,只要把图片移到根目录就可以了。这样很不方便,也不合理,针对这样的问题,可以使用html-webpack-plugin插件解决。

html-webpack-plugin

作用是解决文件路径的问题。

  1. 安装html-webpack-plugin
yarn add html-webpack-plugin -D
  1. 修改webpack.config.js
const path = require('path')

// 引入html-webpack-plugin插件
const HTMLWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.join(__dirname, './dist/'),
        filename: 'bundle.js'
    },
    // 模式有三种,development、production、none
    mode: 'none',

    module: {// 模块设置
        rules: [// 打包规则
            {
                test: /\.css$/, // 匹配css文件
                use: [// 使用loader,顺序不能错
                    'style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.(bmp|png|jpg|gif|svg)$/, // 匹配图片
                use: [// 使用loader
                    'file-loader'
                ]
            }
        ]
    },
    plugins: [
        // 使用html-webpack-plugin插件
        new HTMLWebpackPlugin({
            // 此插件作用是将 index.html 打包到 bundle.js 所在目录中, 
            // 同时也会在 index.html 中自动的 <script> 引入 bundle.js 
            // 注意:其中的文件名 bundle 取决于上面output.filename中指定的名称
            template: './index.html'
        })
    ]
}
  1. 修改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>
    <!-- 模拟一下vue的index.html -->
    <div id="app"></div>
</body>
<!-- 不需要自己引入JS,html-webpack-plugin会自动将JS引入 -->
<!-- <script src="./dist/bundle.js"></script> -->
</html>
  1. 重新打包
yarn build

这时看到dist目录中多了index.html,并且自动引入了bundle.js

在这里插入图片描述

  1. 运行dist目录里的index.html
    这时图片就能正常显示了。

我们看别人写的Vue的项目,只有一个index.html,并且没有引用任何JS就能跑起来,就是因为有了这个插件。

实时重新加载

上面的例子中,每次改动都要重新打包项目才能看到效果,为了解决这个问题,可以采用webpack提供的工具webpack-dev-server,每次修改代码都会自动打包并重新刷新页面。

  1. 安装webpack-dev-server
yarn add webpack-dev-server -D
  1. 修改webpack.config.js
const path = require('path')

// 引入html-webpack-plugin插件
const HTMLWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.join(__dirname, './dist/'),
        filename: 'bundle.js'
    },
    // 模式有三种,development、production、none
    mode: 'none',

    module: {// 模块设置
        rules: [// 打包规则
            {
                test: /\.css$/, // 匹配css文件
                use: [// 使用loader,顺序不能错
                    'style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.(bmp|png|jpg|gif|svg)$/, // 匹配图片
                use: [// 使用loader
                    'file-loader'
                ]
            }
        ]
    },
    plugins: [
        // 使用html-webpack-plugin插件
        new HTMLWebpackPlugin({
            // 此插件作用是将 index.html 打包到 bundle.js 所在目录中, 
            // 同时也会在 index.html 中自动的 <script> 引入 bundle.js 
            // 注意:其中的文件名 bundle 取决于上面output.filename中指定的名称
            template: './index.html'
        })
    ],
    // 实时重新加载,不需要每次修改都手动打包
    devServer: {
        contentBase: './dist'
    }
}
  1. 执行命令
.\node_modules\.bin\webpack-dev-server --open

服务就启动了,页面也会自动打开。
4. 修改style.css查看效果

body {
    background-color: red;
    /* background-image: url(../images/background.bmp); */
}

这时页面的背景图自动消失,底色变成红色。
5. 简化启动命令
.\node_modules.bin\webpack-dev-server --open
这个命令太长了,我不喜欢,所有使用自定义命令别名搞个简单的。
改一下package.json,在scripts中添加

"dev": ".\\node_modules\\.bin\\webpack-dev-server --open"

再执行一下命令

yarn dev

服务起来了,美滋滋_

Babel 浏览器兼容性

Babel的作用是将ES6语法的代码转换成ES5的语法,让旧版本的浏览器能兼容。

  1. 安装Babel
yarn add babel-loader @babel/core @babel/preset-env -D
  1. 修改webpack.config.js
const path = require('path')

// 引入html-webpack-plugin插件
const HTMLWebpackPlugin = require('html-webpack-plugin')

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.join(__dirname, './dist/'),
        filename: 'bundle.js'
    },
    // 模式有三种,development、production、none
    mode: 'none',

    module: {// 模块设置
        rules: [// 打包规则
            {
                test: /\.css$/, // 匹配css文件
                use: [// 使用loader,顺序不能错
                    'style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.(bmp|png|jpg|gif|svg)$/, // 匹配图片
                use: [// 使用loader
                    'file-loader'
                ]
            },
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/, // 排除的目录
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env'] // 内置转换工具
                    }
                }
            }
        ]
    },
    plugins: [
        // 使用html-webpack-plugin插件
        new HTMLWebpackPlugin({
            // 此插件作用是将 index.html 打包到 bundle.js 所在目录中, 
            // 同时也会在 index.html 中自动的 <script> 引入 bundle.js 
            // 注意:其中的文件名 bundle 取决于上面output.filename中指定的名称
            template: './index.html'
        })
    ],
    // 实时重新加载,不需要每次修改都手动打包
    devServer: {
        contentBase: './dist'
    }
}
  1. 修改main.js
    写一些ES6的代码
let a = 1

const arr = [1, 2, 3]

arr.forEach(item => {
    console.log(item)
})
  1. 打包一下
yarn build

看到打包后代码编程ES5语法了

在这里插入图片描述

vue-loader打包Vue文件组件

在这之前必须保证项目已经安装了vue。

  1. 安装vue-loader
yarn add vue-loader vue-template-compiler -D
  1. 修改webpack.config.js
const path = require('path')

// 引入html-webpack-plugin插件
const HTMLWebpackPlugin = require('html-webpack-plugin')

// 1.引入vue-loader插件
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.join(__dirname, './dist/'),
        filename: 'bundle.js'
    },
    // 模式有三种,development、production、none
    mode: 'none',

    module: {// 模块设置
        rules: [// 打包规则
            {
                test: /\.css$/, // 匹配css文件
                use: [// 使用loader,顺序不能错
                    'style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.(bmp|png|jpg|gif|svg)$/, // 匹配图片
                use: [
                    'file-loader'
                ]

            },
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/, // 排除的目录
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env'] // 内置转换工具
                    }
                }
            },
            // 3.添加vue文件的处理规则
            {
                test: /\.vue$/,
                use: [
                    'vue-loader'
                ]
            }
        ]
    },
    plugins: [
        // 使用html-webpack-plugin插件
        new HTMLWebpackPlugin({
            // 此插件作用是将 index.html 打包到 bundle.js 所在目录中, 
            // 同时也会在 index.html 中自动的 <script> 引入 bundle.js 
            // 注意:其中的文件名 bundle 取决于上面output.filename中指定的名称
            template: './index.html'
        }),
        // 2.使用vue-loader插件
        new VueLoaderPlugin()
    ],
    // 实时重新加载,不需要每次修改都手动打包
    devServer: {
        contentBase: './dist'
    }
}
  1. 在src目录下添加App.vue
<template>
  <div>
    <p class="text" v-text="msg"></p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg: "我是Vue组件"
    };
  }
};
</script>

<style scoped>
.text {
  color: red;
}
</style>
  1. 修改main.js
    在main.js中引入Vue和App.vue
import Vue from 'vue'
import App from './App.vue'

new Vue({
    el: '#app',
    template: '<app></app>',// Vue实例化时会把template属性的内容加载到el指定的元素中
    components: {
        app: App
    }
})
  1. 启动服务
yarn dev

这时发现浏览器报错

在这里插入图片描述

原因分析,打开node_modules目录找到vue目录,打开package.json,发现main属性指向的是dist/vue.runtime.common.js
Vue分为了两块

  • 编译器 用来编译template模板编程JS渲染函数的代码
  • vue.runtime.common.js 运行时,用来创建Vue实例和渲染处理虚拟DOM对象等代码,没有编译器功能,无法解析template
    dist/vue.js则是Vue的完整版,包含编译器和运行时,如果直接引入dist/vue.js即可解决问题
    但是这样会由于引入较大的JS库,使得打包的文件太过臃肿
    最佳解决方法在下面
import Vue from 'vue'
import App from './App.vue'

new Vue({
    el: '#app',
    // 使用rander方法来渲染组件
    // render: function(h){
    //     return h(App)
    // }
    render: h => h(App) // ES6写法
})

现在就可以看到效果了。

模块热替换(HMR)

模块热替换(hot module replacement 或 HMR)是webpack最有用的功能之一,可以在不刷新整个页面的前提下,局部刷新修改的组件。

  1. 修改webpack.config.js
    一共有三步
const path = require('path')

// 引入html-webpack-plugin插件
const HTMLWebpackPlugin = require('html-webpack-plugin')

// 1.引入vue-loader插件
const VueLoaderPlugin = require('vue-loader/lib/plugin')

// ***模块热部署第一步
const webpack = require('webpack')

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.join(__dirname, './dist/'),
        filename: 'bundle.js'
    },
    // 模式有三种,development、production、none
    mode: 'none',

    module: {// 模块设置
        rules: [// 打包规则
            {
                test: /\.css$/, // 匹配css文件
                use: [// 使用loader,顺序不能错
                    'style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.(bmp|png|jpg|gif|svg)$/, // 匹配图片
                use: [
                    'file-loader'
                ]

            },
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/, // 排除的目录
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env'] // 内置转换工具
                    }
                }
            },
            // 3.添加vue文件的处理规则
            {
                test: /\.vue$/,
                use: [
                    'vue-loader'
                ]
            }
        ]
    },
    plugins: [
        // 使用html-webpack-plugin插件
        new HTMLWebpackPlugin({
            // 此插件作用是将 index.html 打包到 bundle.js 所在目录中, 
            // 同时也会在 index.html 中自动的 <script> 引入 bundle.js 
            // 注意:其中的文件名 bundle 取决于上面output.filename中指定的名称
            template: './index.html'
        }),
        // 2.使用vue-loader插件
        new VueLoaderPlugin(),

        // ***模块热替换第二步
        new webpack.HotModuleRepalcementPlugin()
    ],
    // 实时重新加载,不需要每次修改都手动打包
    devServer: {
        contentBase: './dist',

        // ***模块热替换第三步
        hot: true
    }
}
  1. 重启服务
yarn dev
  1. 修改App.vue
<template>
  <div>
    <p class="text" v-text="msg"></p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg: "我是Vue组件111" // 随便修改一下查看效果
    };
  }
};
</script>

<style>
.text {
  color: red;
}
</style>

现在就可以愉快开发了,哈哈_

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值