zl程序教程

您现在的位置是:首页 >  前端

当前栏目

webpack入门教程

2023-09-11 14:19:18 时间

webpack相关

1. webpack相关配置

2. 安装

  1. 新建一个文件夹webpack_demo
  2. 初始化package.json
npm init -y
  1. 安装webpack
npm install --save-dev webpack webpack-cli
//如果是使用的webpack版文为4x需要安装CLI,如果不是,反之
  • 官方不推荐全局安装,会使你的项目锁定到webpack的固定版本。详情 点击
  • 关于安装的更多信息,详情 点击
  1. 安装之后,就会多一个webpack,运行webpack -v查看是否安装成功,如果是局部安装需要进入到\node_modules\.bin下进行输入

可能会遇到的问题

  • 在运行安装命令的时候也可能会遇到一下报错Refusing to install package with name "webpack" under a package,这是因为 点击
  • 当输入命令之后,可能会出现报错:无法将“webpack”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
  • 解决措施:
    1. 全局安装webpack
    2. 如果不想全局安装,打开package.json,找到scripts输入以下代码,然后运行npm run dev
	  "scripts": {
	    "dev": "webpack"
	  },
  • 解决问题的原因
    1. 当我们运行scripts中的命令的时候,他寻找包的流程为:从当前项目的node_modules目录下寻找,如果找不到,则去全局寻找
    2. 如果没有运行scripts中的命令,直接运行包暴露出的命令,他会直接到全局寻找

3. 基本使用

  • 打包的方式有两种 详情 点击
    1. 不使用配置文件
    2. 使用配置文件

3.1 不使用配置文件打包

  • 命令 webpack <entry> [<entry>] -o <output>
    • entry : 表示入口文件(目前可以理解成我们要打包的文件),可以是文件名或者文件的路径
    • output : 表示我们最终的打包的文件名称,可以是文件名或者文件的路径
    • 中括号表示可以指定多个入口
  1. 让我们在webpack_demo的根目录下新建index.js文件,在文件中写上如下代码

index.js

	//index.js
	function helloWorld() {
	    console.log('Hello World')
	}
	helloWorld()

终端 输入下面的命令

webpack index.js -o index.bundle.js
  • bundle没有什么特别的含义,相当于一个标识,表示打包后的文件
  • 如果报错的同学,进行了 scripts配置,需要修改为下面代码,运行npm run dev
	  "scripts": {
	    	"dev": "webpack index.js -o index.bundle.js"
	  },
  • 打包完成后在我们的根目录下就会多出文件index.bundle.js,打开之后就可以看到被打包后的压缩后的代码

指定打包模式

  • 命令 webpack <entry> [<entry>] --mode development -o <output>
    • 默认生产模式(压缩代码)
    • --mode用来修改打包的模式,详情 点击
    • 运行之后你就会,打开被打包的文件,没有被压缩

3.2 使用配置文件打包

  • webpack 默认的配置文件为 webpack.config.js,我们所有的配置都可以在这个文件中写,且这个文件最好放在根目录下
    • 我们也可以运行命令webpack [--config webpack.config.js]来修改配置文件名称
    • 配置文件的结构,请查看
  1. 我们在根目录下新建webpack.config.js文件,写上如下代码
const path = require("path")

module.exports = {
    entry: './index.js',
    output: {
        path: path.resolve(__dirname, "dist"),
        filename:"bundle.js"
    }
}
  1. 直接运行命令webpack,或者npm run dev(已经配置过scripts的同学)
  2. 你会发现在根目录下多出了dist文件夹,里面有已经为我们打包好的文件bundle.js

对于文件中的一些代码的说明

  • entry 入口文件,他后面可以跟字符串,对象,数组,可以查看配置结构
  • output 输出文件路径与文件名(第二个参数)
    • path指定文件输出的路径
    • filename 输出的文件名
      • 可以传递参数,形式为"[name].js",他只能与入口文件的对象形式配合使用,对象的key也就是属性名,对传递到参数中,将[name]替换,演示请看下面的代码
    • __dirname获取当前文件所在的绝对路径
    • resolve 进行路径的拼接 ,详情点击
const path = require("path")

module.exports = {
    entry: {
    	index:'./index.js'
    },
    output: {
        path: path.resolve(__dirname, "dist"),
        filename:"[name].bundle.js"
    }
}
//打包后的文件名为 index.bundle.js

4. mode

  • 当我们进行打包的时候,会发现命令行终端会给我们一些警告
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/
  • 他的意思是我们进行打包的模式(环境)还没有指定

4.1 打包环境指定

  • mode种类

    1. production
    2. development
    3. none
  • 我们可以配置文件中添加

module.exports = {
	mode:'development'
}
  • 当我们再次运行命令打包的时候,警告就不会出现了,并且打包出来的代码是没有经过压缩的

5. loader

loader的作用

  • 首先要明白webpack只认识js,先让他处理其他的文件,如.png,.less等,根本不可能啊,因为他只认识js
  • 所以loader就横空出世了,他就负责将其他文件格式转化为js,然后webpack就可以处理他们了

5.1 url-loader

url-loader的作用

  • 主要用来对各种图片格式进行处理,如.jpeg,.png
  • 将图片打包成 base64 格式
  • file-loader的功能与url-loader的功能差不多,都是对图片进行处理的loader
  • 当打包超过限制的时候,url-loader会自动调用file-loader

5.1.1 url-loader安装

npm install --save-dev url-loader

5.1.2 url-loader配置

  • webpack.config.js中写上如下代码
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 1024*50
            }
          }
        ]
      }
    ]
  }
}

说明
对于webpack.config.js我们做了如下的改动

  1. 新增moudle对象,对象里面有一个rules的数组,数组中包含的是一个对象
  2. test后面跟的是一个正则表达式,表示的是我们要对那些格式的文件做处理
  3. use表示使用那些loadertest的文件做处理
  4. loader具体使用的loader
  5. options:配置选项
  6. limit:对于图片的限制,以字节B为单位,1024B=1KB,所以我们采取了1024*50的写法

5.1.2 url-loader实战

  1. 找到两个图片(大小差距大一些),在根目录新建images,并把两张图片放到文件夹中,这里用了两张图片并分别重命名img_big.png(95KB),img_small.jpg(9KB),配置中我们的限制为50KB
    images文件夹

2.运行webpack或者npm run dev(配置scripts的同学)

  • 我们会发现命令行端口报错:较大的图片解析失败,原因:没有file-loader
    在这里插入图片描述
  • 同时,我们也发现dist文件夹下已经打包出文件,我们进入文件
    • Ctrl + F,搜索img_small.jpg
      在这里插入图片描述
  • 我们会发现在限制内的图片已经被打包成base64编码图片了
  1. 为了解决报错,我们安装file-loader
	npm install file-loader -D
  1. 继续运行webpack
  2. 打包之后没有报错,接着打开dist文件夹,发现超出限制的图片打包到了dist文件夹下
    在这里插入图片描述

5.2 babel-loader

babel-loader的作用

  • babel最主要的作用是将ES6的代码转化成ES5的代码
  • 当然,它还可以转换JSX语法
  • 这些在babel的官网都有说明,详情 点击

5.2.1 babel-loader安装

  • webpack官网有两行安装的代码,一个是安装babel6,一个是babel7,我们这里使用babel7
npm install babel-loader@8.0.0-beta.0 @babel/core @babel/preset-env webpack
  • @babel/corebabel的核心库,一般babel的库都已@开头
  • @babel/preset-env主要内置了一些转换的规则
  • 如果我们想识别JSX语法的话,还需要安装babel的插件,详情点击
  • 还需要在test中添加对JSX语法的支持
	npm install --save-dev @babel/plugin-transform-react-jsx

5.2.2 babel-loader配置

module: {
  rules: [
    {
      test: /\.(js|jsx)$/,
      exclude: /(node_modules|bower_components)/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env'],
          plugins: ["@babel/plugin-transform-react-jsx"]
        }
      }
    }
  ]
}
  • exclude表示排除对某些包的编译
  • presets表示规则文件
  • plugins功能扩展使用的插件

5.2.3 babel-loader实战

ES6转ES5

  1. 我们在根目录下新建src文件夹,并新建es6.js,表示里面写的有es6的代码
  2. es6.js中写上如下代码,并在入口文件引入
const helloworld = async() => {
    console.log('helloworld')
}
helloworld()
  1. 入口文件引入
import './src/es6'
  1. 为了观察转换效果,我们可以先把配置文件中的规则和插件注释掉进行打包,运行webpack
   /* presets: ['@babel/preset-env'],
   plugins: ["@babel/plugin-transform-react-jsx"] */
  1. 打包完成后,打开打包文件,搜索helloworld,结果应该如下,我们发现代码原封不动的打包到了文件中
    在这里插入图片描述
  2. 将注释掉的规则释放,再次打包,并查看
    在这里插入图片描述
  • 我们发现打包之后的箭头函数async都不见了踪影

转化JSX语法

  • 想要使用JSX语法,我们需要下载react,react-dom
npm install react react-dom -S
  • 写上如下代码,并在入口文件中引入
import React,{Component} from 'react'

export default class HelloWorld extends Component{
    render() {
        return (
            <div>HelloWorld</div>
        )
    }
}

入口文件引入

	import HelloWorld from './src/helloWorld.jsx' 
  • 此时我们将webpack.config.js插件配置注释掉
/*  plugins: ["@babel/plugin-transform-react-jsx"] */
  • 运行打包命令,你会发现他会报错,原因是不识别JSX语法
    在这里插入图片描述
  • 我们将注释清掉,再次运行打包命令,你就会发现他已经不报错了

5.3 less-loader

less-loader的作用

  • less代码转化为css代码
  • 但是css代码webpack还不能处理,需要css-loader转化成js
  • style-loader是用来将css代码注入到style标签中
  • 所以我们需要下载的包有less less-loader css-loader style-loader
  • 详情点击

5.3.1 less-loaer安装

npm install --save-dev less-loader less css-loader style-loader

5.3.2 less-loaer配置

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
            }]
        }]
    }
};

5.3.3 less-loaer实战

  • src文件夹下新建style.less文件,写上如下代码
@color:red;

body{
    background-color:@color;
}
  • 运行打包命令,并打开打包后的文件,搜索background,你会发现变量已经被编译了
    在这里插入图片描述

6.plugins

plugins的作用

  • plugins的作用与loader相反,将js代码转化成相应的格式
  • plugins还提供了一些功能扩展

6.1 mini-css-extract-plugin

作用

6.1.1 mini-css-extract-plugin安装

npm install --save-dev mini-css-extract-plugin

6.1.2 mini-css-extract-plugin配置

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader',"css-loader","less-loader"],
      },
    ],
  },
};
  1. 在配置文件引入插件,插件暴露出来的是一个构造函数
  2. 在配置对象中添加plugins选项,如图
  3. 在处理样式的配置中,使用插件的属性loader,在这里我们使用了另一种配置字符串配置的方式,但是需要我们注意的而是
    • 要把配置的style-loader删去,因为style-loader的作用是生成style标签,而我们把它css提取出去,就不需要了。如果保留style-loader他会报错
      在这里插入图片描述

6.1.3 mini-css-extract-plugin实战

  1. 运行打包命令,我们就会发现在打包输出的dist文件夹下,多出了一个index.css文件
  2. 当然我们还可以在new MiniCssExtractPlugin()参数中传递一些配置
    1. filename打包输出的文件名,他可以是一个路径
    2. chunkFilename打包输出的模块名,不常用
  3. 再次运行打包,你会发现打包输出的文件名就是配置的名字

6.2 html-webpack-plugin

作用

  • 为html文件中引入的外部资源如script、link动态添加每次compile后的hash,防止引用缓存的外部文件问题
  • 可以生成创建html入口文件,比如单页面可以生成一个html文件入口,配置N个html-webpack-plugin可以生成N个页面入口
  • 详情 点击

6.2.1 html-webpack-plugin安装

npm install --save-dev html-webpack-plugin

6.2.2 html-webpack-plugin配置

var HtmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path');

module.exports = {
  plugins: [new HtmlWebpackPlugin()]
};

6.2.3 html-webpack-plugin实战

  1. 当我们写完上面的配置的时候,可以运行命令打包一下,他会给我们生成默认的配置
  • 他在打包目录dist文件夹下自动生成了index.html文件
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Webpack App</title>
  <meta name="viewport" content="width=device-width, initial-scale=1"></head>
  <body>
  <script src="index.bundle.js"></script></body>
</html>
  • 自动为我们注入了js脚本文件
  • 自动生成的title为webpack app
    但是这都我们我们想要的,我们需要我们自己可以定制title,也可以随意引入其他依赖的库,这应该怎么做呢。

html-webpack-plugin高度配置

  • 详情点击
  • 我们可以在构造函数中传递配置选项
    • title最终会被插入到title标签中
    • filenamehtml的文件名字
    • template将配置的内容注入的模板,在这个模板中我们可以引入CDN,他后面可以跟一个路径
new HtmlWebpackPlugin({
     title:'Hello webpack',
     filename: 'main.html',
     template:'template.html'
 })
  • 那么模板如何编写呢
    • title的值需要用ejs的模板语法来实现
    • 想要引入其他CDN可以在模板中直接引入
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- ejs模板语法 -->
    <title><%= htmlWebpackPlugin.options.title %></title>
    <!-- 引入 jQuery的CDN -->
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
</head>
<body>
    
</body>
</html>
  • 运行打包命令进行打包
    • 在打包目录下就生成了我们想要的模板,其他配置也可点击查看
    • 这个时候我们可以在template.htmlindex.js中写上如下代码

index.js

import React from 'react'
import ReactDOM from 'react-dom'
ReactDOM.render(<HelloWorld/>,document.getElementById('root'))

template.html

<body>
    <div id="root"></div>
</body>
  • 再次运行进行打包

6.3 devServer

作用

  • 当我们写完一个文件保存之后,他会自动编译,并更新浏览器
  • 详情 点击

6.3.1 devServer安装

npm install webpack-dev-server -D

6.3.2 devServer配置

    devServer: {
        contentBase: path.join(__dirname, 'dist'),
        compress: true,
        port: 8080
    },
  • contentBase,对于那个目录开启devServer(我们要显示那个目录中的内容)
  • compress是否压缩,启用gzip 压缩
  • port运行端口号
  • scripts中配置一下命令
"start": "webpack-dev-server",
"build": "webpack"

注意
在webpack5中contentBase属性已经别删除,详情点击

6.3.2 devServer实战

  • 运行npm start
  • 当我们在helloWorld.jsx中写上一些代码时,打开浏览器或者终端,我们会发现他会自动更新
  • 当我们运行npm run build,他就会在打包
  • 这时我们会发现我们差不多可以搭建一个React的脚手架了

7. webpack性能优化


7.1 打包分析


详情点击
下载

npm install --save-dev webpack-bundle-analyzer

配置

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}

然后我们可以修改package.json命令为

"build": "webpack --profile --json > stats.json"

他的意思是将打包过程的描述放在stats.json文件中

  • 然后我们运行命令npm run build,等待打包完成,当打包完成之后他会出现以下图片
    在这里插入图片描述
  • 而我们打包出来文件的目录是这个样子的 在这里插入图片描述
  • 而图片便是的就是一个包围结构,上面的包围着下面的,图片的大小代表的包的体积的大小

github源码地址:https://github.com/whynot-todo/webpack_demo.git