Webpack初识

2个月前 (10-17) 157次浏览 已收录 0个评论

导读

Webpack是一种前端资源构建工具,也可以理解成静态模块打包器。它能将所有的前端资源文件作为模块处理,然后根据模块的依赖关系进行静态分析,打包生成对应的静态资源(称为bundle),它还能处理浏览器端js的兼容性问题。


五个核心概念

Entry 入口指示

指示Webpack以哪个文件为入口起点开始打包,分析构建内部依赖图。

Output 输出指示

指示Webpack打包后的资源bundles输出到哪里去,以及如何命名。

Loader

Loader让Webpack能够处理非Java Script文件,因为webpack自身只理解JS。

Plugins

插件Plugins可以用来执行范围更广的任务,插件的范围包括从打包优化和压缩,一直到重新定义环境中的变量等。

Mode

  • developmet开发模式:让代码能在本地调试运行
  • production生产模式:让代码能优化上线

  • webpack只能处理js/json文件
  • 生产环境和开发环境将ES6模块化编译成浏览器能识别的模块化
  • 生产环境会压缩JS代码


隔行变色

通过一个小案例来学习webpack的使用。

初始化项目

  • 新建项目空白目录,并运行npm init -y 命令,来初始化包管理配置文件 package.json
  • 新建src源代码目录
  • 新建src -> index.html 首页和src -> index.html脚本文件
  • 初始化首页基本结构
  • 运行npm install jquery -S 命令,安装jQuery
  • 通过ES6模块化的方式导入jQuery,实现列表隔行变色的效果。
  • 安装webpack相关的两个包npm install webpack@5.42.1 webpack-cli@4.7.2 -D

配置webpack

  • 在项目根目录中,创建webpack.config.js的文件,并初始化以下配置
module.exports={
    mode:'development'
}
  • 在package.json的scripts节点下,新增dev脚本
"scripts": {
    "dev1":"webpack"
  }

index.js

//使用es6导入jQuery

//使用es6在jquery导入一个成员,用$来接收
import $ from 'jquery'

//入口函数
$(function(){
    //实现奇偶行变色
    $('li:odd').css('background-color','red');
    $('li:even').css('background-color','green');
})

打包构建生成main.js

  • 可以通过终端npm run dev1来启动webpack进行项目的打包构建
npm run dev1

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>隔行变色</title>

    <!-- 这样导入会报错,因为js的语法太高级,浏览器不支持, -->
    <!-- <script src="./index.js"></script> -->

    <!-- 需要使用webpack来解决兼容性问题,
    使用通过webpack对index.js生成的main.js -->
    <script src="../dist/main.js"></script>
</head>
<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
        <li>7</li>
        <li>8</li>
        <li>9</li>
    </ul>
</body>
</html>
结果演示

webpack中的默认约定

在webpack4.x和5.x的版本中,有以下默认约定

  • 默认的打包入口文件为src -> index.js
  • 默认的输出文件路径为dist -> main.js
  • 也可以在webpack.config.js中修改打包的默认的规定

修改webpack.config.js文件

//使用node.ja的道出语法,向外导出一个webpack的配置对象

const path1 = require('path') //导入node.js中专门操作路径的模块

module.exports={
    //打包入口文件路径
    entry:path1.join(__dirname,'./src/index.js'),
    //__dirname代表它所处的那一个目录,即文件根目录,用join和后面的路径进行拼接
    //输出文件的存放的路径
    output:{
        path:path1.join(__dirname,'./dist'),
        //输出文件的名称,并放在js目录下
        filename:'js/bundle.js'
    }
}
上部分的操作有缺点,就是每次修改代码,都要重新执行命令,很繁琐,可通过插件来解决:只要保存好,会自动执行命令,直接可以在浏览器里看运行结果

插件

webpack-dev.server

  • 类似于node.js中的nodemon工具
  • 每当修改了源代码,webpack会自动进行项目的打包和构建。

安装webpack-dev-server

npm install webpack-dev-server@3.11.2 -D

配置webpack-sev-server

  • 修改package.json -> scripts中的dev命令
"scripts": {
  "dev1": "webpack serve"
}
  • 再次运行npm run dev1 命令,重新进行项目的打包
  • 此时终端会有一个光标一直闪烁,并进行更新和打包
  • 在浏览器中访问http://localhost:8080地址,查看自动打包效果

webpack-dev-server会启动一个实时打包的http服务器

此时需要安装一个和webpack版本兼容的webpack-cli,我的安装版本如下

npm install webpack-cli@4.9.0 -D

此时的动态生成的bundle.js不在dist目录下,而是放在了内存里,也就是隐藏在根目录里了,所以项目结构里看不到,也就是不能在html里引用dist里的bundle.js了,不然得不到刚修改的效果代码

<!-- 加载和引用内存中(根目录)中的bundle.js -->
   <script src="/bundle.js"></script>

html-webpack-plugin

运行命令安装插件,可以实现直接打开8080端口后就打开首页了。因为上面的代码会有缺点,就是每次访问都要去src里访问,比较麻烦。

npm install html-webpack-plugin@5.3.2 -D

在webpack-config.js中配置html-webpack-plugin,注意此时下面会有上面内容代码。

//使用node.ja的道出语法,向外导出一个webpack的配置对象

//导入html-webpack-plugin插件,得到一个构造函数
const HtmlPlugin=require('html-webpack-plugin')
//创建html插件的实例对象
const htmlPlugin=new HtmlPlugin({
    template:'./src/index.html',//指定源文件的存放路径
    filename:'./index.html'//指定生成文件的存放路径
    // 并且生产的首页代码还是放在了内存里,项目结构里看不到
})
//接着使插件生效

const path1 = require('path') //导入node.js中专门操作路径的模块

module.exports={
    mode:'development',

    //打包入口文件路径
    entry:path1.join(__dirname,'./src/index.js'),
    //__dirname代表它所处的那一个目录,即文件根目录,用join和后面的路径进行拼接
    //输出文件的存放的路径
    output:{
        path:path1.join(__dirname,'./dist'),
        //输出文件的名称
        filename:'bundle.js'
    },


    //插件的数组,webpack运行时会加载这些插件
    plugins:[htmlPlugin]//通过plugins节点,使htmlplugin插件生效
}

然后重新执行npm run dev1命令

此时要注意,内存里的文件和项目结构里的文件不是一个文件,只是复制出来的,两个互不影响,即网页不再从index.html里的script引入js了,而是html-webpack-plugin这个插件自动引入的

  • 通过html插件复制到项目根目录中的index.html页面,也被放到了内存中
  • html插件在生成的index.html页面中,会自动注入了打包的bundle.js文件。

devServer节点

追加webpack-config.js配置

devServer:{
        open:true,//初次打包完成后,自动打开浏览器
        host:'127.0.0.1',//实时打包所使用的主机地址
        port:8080//实时打包所使用的端口号
    }

loader

因为webpack只能打包js文件,其他类型文件,webpack默认处理不了,需要调用loader加载器才可以正常打包,否则会报错

loader加载器的作用:协助webpack打包处理特定的文件模块,比如:

  • css-loader可以打包处理css相关的文件
  • babel-loader可以打包处理webpack无法处理的高级js语法。

导入css

在index.js中导入css样式

//导入样式(因为在webpack中,一切皆模块,都可以通过es6导入语法进行导入使用)
import './index.css'

此时会报错,因为缺少loader,所以要安装处理css的loader

npm install style-loader@3.0.0 css-loader@5.2.6 -D

配置webpack-config.js里的配置规则,在module -> rules数组中,添加loader规则如下:

//所有第三方文件模块的匹配规则,这里也是放在module.export里
module:{
    rules:[
        //文件后缀名的匹配规则
        {test:/\.css$/,use:['style-loader','css-loader']}
    ]
}

其中test表示匹配的文件类型,use表示对应要调用的loader

loader的调用过程

use:[‘style-loader’,’css-loader’]的执行顺序
  • webpack默认只能打包处理js文件,处理不了其他文件
  • 由于代码中包含css文件,因此webpack处理不了
  • 接着webpack会查找webpack-config.js这个配置文件,看module.rules数组中是否配置了对应的loader加载器。
  • webpack把这个css文件,转交给最后一个loader进行处理(即css-loader)
  • 当css-loader处理完毕之后,会把处理结果,转交下一个loader(即style.loader)
  • 当style.loader处理完毕之后,发现没有下一个loader了,于是就把处理结果,转交给了webpack
  • webpack再把结果合并到/dist/bundle.js中,最终生成打包好的文件

  • use数组中指定的loader的顺序是固定的
  • 多个loader的调用顺序:从后往前调用

导入less

在index.js中导入

//导入less
import './index.less'

安装less的loader

npm install less-loader@10.0.1 less@4.1.1 -D

配置webpack-config.js里的module ->rules数组,添加loader规则

//所有第三方文件模块的匹配规则
    module:{
        rules:[
            //文件后缀名的匹配规则
            {test:/\.css$/,use:['style-loader','css-loader']},
            //因为less的loader需要用到css-loader,所以要把它放在最后面
            {test:/\.less$/,use:['style-loader','css-loader','less-loader']}
        ]
    }

打包处理样式表中与URL路径相关的文件(比如图片)

安装相关loader

npm i url-loader@4.1.1 file-loader@6.2.0 -D

在index.html中添加img标签,里面的图片路径需要index.js动态指定

<img src="" alt="" class="box">

在index.js中导入图片

//导入图片
import logo from './img/logo.jpg'
//给img标签的src动态赋值
$('.box').attr('src',logo)
//其中某个模块中,使用from接收到的成员为undefined,则没有必要进行接收,比如以上几个部分。

webpack-config.js添加loader

//所有第三方文件模块的匹配规则
    module:{
        rules:[
            //文件后缀名的匹配规则
            {test:/\.css$/,use:['style-loader','css-loader']},
            {test:/\.less$/,use:['style-loader','css-loader','less-loader']},
            {test:/\.jpg|png|gif$/,use:'url-loader?limit=22229'}
        ]
    }

其中?之后的是loader的参数项:

  • limit用来指定图片的大小,单位是字节,可以省略不指定
  • 只有小于limit(22229)大小的图片,才会被转为base64格式的图片,因为base64不会频繁对服务器发起请求。所以最后生成包里的src也是base64的字符串

babel-loader处理js文件中高级语法

对于那些连webpack都无法处理的高级的js语法,需要借助babel-loader进行打包处理。

安装相关loader

npm install babel-loader@8.2.2 @babel/core@7.14.6 @babel/plugin-proposal-decorators@7.14.5 -D

添加loader规则

//注意:必须使用exclude指定排除项,因为node_modules目录下的第三方包不需要被打包,只需要针对自己写的代码
{test:/\.js$/,use:'babel-loader',exclude:/node_modules/}

配置babel-loader

在项目根目录下,创建babel.config.js的配置文件,定义babel的配置项如下:

module.exports={
    //声明babel可用的插件
    //将来,webpack在调babel-loader的时候,会先加载plugins插件来使用
    plugins:[['@babel/plugin-proposal-decorators',{legacy:true}]]
}

配置build命令

以上的部分只是把生成的包放在了内存里,可以使用build把打包后的文件发给后端。
在package.json文件的scripts节点下,新增build命令:
"scripts": {
   "dev1": "webpack serve",
   "build1":"webpack --mode production" 
 }
  • 开发环境中,运行dev1命令
  • 项目发布时,运行build1命令
  • 加server还是会放在内存里,不加会放在磁盘里

–model是一个参数项,用来指定webpack的运行模式,即生产模式,压缩代码。通过–model指定的参数项,会覆盖webpck.config.js种的model选项。

运行命令重新打包发布

npm run build1

小技巧

优化js和图片的存放路径

//配置url-loader中,多个参数之间使用&符号分隔,打包的图片放在images目录下
{test:/\.jpg|png|gif$/,use:'url-loader?limit=1000&outputPath=imgages'},

自动清理dist目录下的旧文件

每次打包后都要手动删除dist目录下的文件,如果想实现自动清理,可以安装clean-webpack-plugin

npm install clean-webpack-plugin@3.0.0 -D

配置webpack-config.js文件

//左侧花括号是解构赋值
const {CleanWebpackPlugin}=require('clean-webpack-plugin')
//插件的数组,webpack运行时会加载这些插件,即使插件生效
plugins:[htmlPlugin,new CleanWebpackPlugin()],

Source Map

开发环境下默认生成的Source Map,记录的是生成后的代码的位置,会导致运行时报错的行号源代码的行号不一致。

开发环境下,推荐在wenbpack.config.js(module.exports)中添加以下配置,即可保证运行时报错的行号源代码的行号一致。

devtool:'source-map'
在发布项目的时候建议关闭sourcemap,因为一旦不关闭,网页报错,用户很容易通过开发者工具定位到源代码的所在行号,也就知道了源代码

只显示定位行号不暴露源码

实际发布的时候(生产模式)可以将devtool的值设置为:

devtool:'nosources-source-map'

也可以直接关闭sourceMap(即不写devtool)


@的优势

如果一个文件层级很深,会出现很多../的情况,它是由内往外查找,如果使用@表示src源代码目录,它从外往里查找。

@/index.js

配置webpack-config.js文件里的module.exports

resolve:{
        alias:{
            //告诉webpack,代码中@符号表示src这一层目录
            '@':path.join(__dirname,'./src')
        }
    }

渣渣龙, 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Webpack初识
喜欢 (0)

您必须 登录 才能发表评论!