webpack学习记录

webpack

  • 一个网页当中的css文件及js文件比较多,这些文件我们都是通过link和script标签导入的,这样导入会导致请求次数过多
  • 在浏览器中运行的代码,我们要考虑一个兼容性问题,最好不要使用最新的语法
  • 我们的页面会有很多的css3.0的代码,这些代码也要考虑兼容性的问题
  • 同一个JS文件在不同的页面中导入了,能否导入一次之后按需加载

处理以上问题,我们可以通过打包技术来解决

目前来讲打包工具很多

1、gulp

2、grunt

3、webpack

4、rollup

什么是webpack

我们可以把webpack理解成是一个项目经理,它本身只会干一件事情就是整合资源,其他什么事情都不会干,它如果想做一个些其他的事情,会找第三方的人(第三放模块)来完成

它可以把很多的松散资源打包一起,可以实现按需加载,同时打包过程中还可以通过加载第三方模块来实现一些特殊效果,比如提高css的兼容性,将ES6的代码转换成ES5

webpack的四个核心点

1、入口(entry)

2、出口(output)

3、模块(loader)

4、插件(plugin)

入口决定了需要打包的文件(决定了程序从什么地方开始),出口决定了程序打包之后生成的地方,loader决定你当前使用什么规则来处理你需要打包的代码,插件决定了打包以后可以干的事情

webpack安装

npm i webpack webpack-cli -D

webpack 打包工具本身

webpack-cli 让webpack可以使用命令行执行

举例:

Person.js

class Person{
    constructor(nickName){
        this.nickName = nickName;
    }
}

export default Person

Student.js

import Person from "./Person.js";
class Student extends Person{
    constructor(nickName,sex){
        super(nickName);
        this.sex = sex;
    }
    sayHello(){
        console.log(`大家好,我叫${this.nickName}`);
    }
}

export default Student

index.js

import Student from './Student.js';

let stu = new Student("张三","男");
stu.sayHello()

现在我们执行 node js/index.js,但是我们发现nodeJS是不支持ESModule,现在我们使用webpack来整合一下

现在我们把需要执行的webpack指令,配置成一个npm的执行脚本,这样可以统一一个命令执行,相当于是对要执行的指令进行一个封装

"scripts": {
	"build":"webpack ./js/index.js -o ./dist"
} 

然后我们只需要执行 npm run build 来进行webpack的打包处理

上面的代码只是进行了简单的webpack的运行,并没有加载任何的配置,这种方式基本不用,因为我们使用webpack除了整合项目之外,还需要大量的第三方模块和插件来完成一些更高级的功能,所以需要一些更精细化的配置行为,这个时候我们开始真正配置webpack

webpack配置

webpack配置分为两种情况

1、生产环境

2、开发环境

生产环境配置

无论哪种配置都要牢记webpack4个核心点

注意:

我们这里虽然配置的是生产环境的配置,但是实际在写mode的配置项时会写development,这要是观察打包之后的代码,因为生产环境打包后的代码会压缩,压缩之后的代码是没有格式的,不方便观察

首先我们在当前项目下新建一个js文件叫做webpack.config.js

//我们把这个文件看成事一个webpack的配置文件,以后的webpack就使用这个配置文件
//webpack的配置文件里面,我们使用的事commonJS模块化规范

const path = require("path");

const config = {
    //mode设置webpack的运行的是一个开发环境
    mode:"development",
    //entry设置webpack的入口文件路径
    entry:path.join(__dirname,"./js/index.js"),
    //output设置webpack打包之后的新文件的文件名和存储路径
    output:{
        filename:"bundle.js",
        path:path.join(__dirname,"./dist"),
        publicPath:"./"
    },
    //module在打包过程中根据自己的需求载入第三方模块添加一些特色功能
    module:{
		rules:[

        ]
    },
    //对打包功能本身添加额外的功能
    plugins:[

    ]
}

module.exports = config

接下来在package.json中修改启动命令,因为我们现在需要通过配置文件来启动打包

"scripts": {
    "build":"webpack --config ./webpack.config.js"
  }

以上代表webpack在启动的时候需要使用webpack.config.js文件作为配置文件使用

babel的配置与使用

现在我们已经对webpack做好了一个基础的配置文件,现在需要提高JS的兼容性,将ES6+的语法转换成ES5的代码,但是webpack本身是不具备这个功能的,它需要借助第三方发的loader来实现,而babel就是专门用于ES代码转换

安装锁需要的包
npm i babel-loader @babel/core -D

babel-loader 基于webpack的babel模块包(依赖包)

@babel/core 实现ES编译的核心(将源代码转换成抽象的语法树AST)

规则配置
module:{
    rules:[
        {
            //匹配所有的js文件
            test:/\.js$/,
            //把node_modules文件夹下面的JS文件排除在JS转换功能以外
            exclude:/node_modules/,
            //当前配置的规则是babel-loader的规则
            loader:"babel-loader"
        }
    ]
},

代码说明:

上面的代码意思,告诉webpack如果匹配到JS文件,就使用第三方模块babel-loader来进行处理,但是并不是所有的文件都需要处理在node_modules文件夹里面的不需要处理

当我们去配置上面的规则之后,我们发现JS代码并没有转换成ES5的代码,为什么?

配置babel的预设信息

如果要让babel来处理自己的JS代码,一定要告诉它你的预设信息是什么(就是你最终想要的效果)

在当前目录下创建一个文件,取名 .babelrc,作为语法转换预设置文件

下载@babel/preset-env包

npm i @babel/preset-env -D

@babel/preset-env 这个名字可以拆分成两个部分来看,这样方便理解:

  • preset 预设好的插件集合包
  • env 目标环境

babel编译ES6+的语法,是通过一个个插件来实现的,但是ES这个东西每年都会有新的提案,新的语法,但是我们不可能一个一个插件的去单独配置,所以有了preset这个东西,因此我们可以理解preset就是一个语法插件集合包,这样我们只用安装一个包,而不需要一个一个插件的安装,就可以很方便的编译新的语法

这个的包作用就是根据当前的配置来进行相应的语法转换

但是在ES里面处理语法之外,还有什么东西?

它还有很多新增的API,Map,Set,Reflect、Proxy等等,这些对象在ES5里面都是不存在的,怎么办?

为了弥补ES5里面没有ES6+新增的对象特点,babel还需要加载一个core-js

npm i @babel/runtime core-js@3 @babel/plugin-transform-runtime -D

1、core-js@3

这个包主要的作用在于实现ES6+新增的语法和API转换

2、@babel/runtime

这个包会在安装@babel/preset-env的时候一起安装,但是我们还是再安装一遍

在实现ES语法转换的时候,@babel/preset-env依赖包会在JS文件中注入一些辅助函数来帮助高版本语法向底版本语法的转换,但是,我们实际项目中会有非常多的JS文件,那么就意味这些辅助函数会在每个JS文件都注入一遍,这个时候通过@babel/runtime将这些辅助函数做成一个npm依赖包,通过导入的方式在所有需要转换的JS文件中才注入辅助函数,从而压缩项目体积,提高代码的复用

3、@babel/plugin-transform-runtime

上面我们提供@babel/runtime将辅助函数作为npm包来进行引用,但是这个应用的过程手动的,需要开发者自己手动在需要转换的JS问及爱你中写入引用代码,通过@babel/preset-env的编译会给JS文件写入一遍辅助函数,所以我们需要把@babel/preset-env写入的辅助函数删除掉,同时又要把@babel/runtime包中的辅助函数自动引入,@babel/plugin-transform-runtime 就可以实现,把preset写入的辅助删除的同时,自动导入runtime打包的辅助函数依赖包

扩展内容

@babel/plugin-transform-runtime有三大作用

1、自动移除语法转换后内联的辅助函数,使用@babel/runtime/helpers里面的辅助函数来替换

2、当代码里面使用core-js的API,会自动引入@babel/runtime-corejs3/core-js-stable,以替换全局引入的core-js/stable

3、当代码中使用Generator / async函数,@babel/runtime/regenerator 以此替换成全局引得regenerator/runtime

注意:

我们在上安装了一个core-js@3包,这个包的作用我们上面也提过,可以让ES5实现ES6+的语法和API,但是无法转换生成器函数和async函数,所以我们会使用@babel/ployfill(已被弃用)这个包来进行补齐,不过这种方式造成全局污染,例如,Promise,我们的ployfill是对浏览器的全局对象重新赋值,重写了Promise及其原型链,这个时候通过库来开发就会出现冲突的问题,这个时候@babel/plugin-transform-runtime的第二条作用就可以解决这个问题

但是现在的情况是,polyfill已经被弃用,那么就意味着不能用这个包来补齐,如果我们分析下polyfill的内部就可以知道,其他它内部是由两个子包组成的,分别是core-js和regenrator-runtime,core-js是干嘛的我们是知道的,regenrator-runtime是用来补齐生成器函数与async函数的,而上面的第三条作用自动引入@babel/runtime/regenerator 等价于 regenerator/runtime,而这个包我们在安装@babel/preset-env的时候就已经内置安装了

基于上面的内容我们还可以安装一个@babel/runtime-corejs3

npm i @babel/runtime-corejs3 -D

配置babel-loader预设

上面我们在项目的根目录中创建的.babelrc文件,这个文件作为我们在webpack中载入babel-loader的配置文件使用

注意:

文件名和文件路径不要随意更改,并且这里写配置的时候语法也不太一样,基本逻辑还是基于对象的键值对,但是键与值的数据格式于传统的不太一样

{
    //预设信息
    "presets":[
        //代表现在使用默认配置好的插件集合包
        [
          "@babel/preset-env",{
                //使用了什么模块就加载什么包,这样打包体积可以小一些
                "useBuiltIns":"usage",
                //代表corejs使用的版本是3
                "corejs":"3",
                "targets":{
                    "browsers":[
                        //最新的2个大版本
                        "last 2 versions",
                        //全球使用人数超过1%的浏览器
                        "> 1%",
                        //排除掉dead
                        "not dead"
                        //这里最终的过滤结果就是通过last 2 versions筛选的浏览器中,全球适用于低于1%,并且官方声明不再维护或者事实上已经有两年没有更新过版本的浏览器
                    ]
                }
            }
        ]
    ],
    "plugins":["@babel/plugin-transform-runtime"]
}

再使用@babel/preset-env的时候,我们可以针对性的做一个配置的调整

useBuiltIns

  • entry:打包在入口文件中导入的API补齐模块
  • usage:自动打包使用额API补齐模块,没用的不管
  • false:默认值

corejs

  • 2:默认值,babel转码的时候使用core-js@2的版本
  • 3:babel转码的时候使用core-js@3的版本

targets

  • broswers:设置目标环境(需要兼容的浏览器)
  • esmodules:允许使用浏览器的ESModule规范,可以设置true或false

modules

  • commonjs:使用commonjs模块化规范
  • auto:跟commonjs一样
  • false:使用ESModule的语法

关于目标环境配置的写法可以参考一下网站

Browserslist

配置html-webpack-plugin

上面生成的JS代码最终都是要在html文件里面使用的,所以我们生产的JS需要自动的插入到所需要的HTML文件中,这个时候我们使用webpack插件html-webpack-plugin,这个插件可以将生成好的文件自动插入到html中

准备一个html文件作为引入打包好的JS文件的模板文件使用

安装插件
npm i html-webpack-plugin -D
配置插件
//我们把这个文件看成事一个webpack的配置文件,以后的webpack就使用这个配置文件
//webpack的配置文件里面,我们使用的事commonJS模块化规范

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin")

const config = {
    //mode设置webpack的运行的是一个开发环境
    mode:"development",
    //entry设置webpack的入口文件路径
    entry:path.join(__dirname,"./js/index.js"),
    //output设置webpack打包之后的新文件的文件名和存储路径
    output:{
        filename:"bundle.js",
        path:path.join(__dirname,"./dist"),
        publicPath:"./"
    },
    //module在打包过程中根据自己的需求载入第三方模块添加一些特色功能
    module:{
        rules:[
            {
                //匹配所有的js文件
                test:/\.js$/,
                //把node_modules文件夹下面的JS文件排除在JS转换功能以外
                exclude:/node_modules/,
                //当前配置的规则是babel-loader的规则
                loader:"babel-loader"
            }
        ]
    },
    //对打包功能本身添加额外的功能
    plugins:[
        new HtmlWebpackPlugin({
            //配置模板文件的位置
            template:path.join(__dirname,"./index.html"),
            //生产的新文件的名称
            filename:"index.html",
            //生产的JS和CSS自动插入
            inject:true
        })
    ]
}

module.exports = config
html-webpac-plugin配置项

title 用于设置html文件的标题

filename 用于设置html文件的名称,默认值就是index.html

template 设置模板文件路径

inject 是否自动把打包文件插入到html当中

favicon 设置icon路径

meta 设置meta信息,配置项的值是一个对象

minify 是否压缩html代码,根据值来设置压缩方式

  • collapseWhitespace 用于清理html中的空行和空白符,将html压缩成一行
  • removeComments 删除注释
  • removeStyleLinkTypeAttributes 删除script中的type属性
  • removeRedundanAttributes 删除多余的属性
  • useShortDoctype 使用短的文档类型

hash 给引入的css和js文件添加hash值

cache 是否缓存

showErrors 编译html的时候,有错误显示错误详情

chunks 有多个入口文件,指定入口文件引入到html中

excludeChunks 排除指定文件无需引入到html中

配置clean-webpack-plugin

我们在生成目录里面,会有一些不需要的文件,这个时候手动删除是非常危险的,所以我们使用clean-webpack-plugin它会自动解析,将不需要的文件删除

安装

npm i clean-webpack-plugin -D

配置

//我们把这个文件看成事一个webpack的配置文件,以后的webpack就使用这个配置文件
//webpack的配置文件里面,我们使用的事commonJS模块化规范

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin")
const {CleanWebpackPlugin} = require("clean-webpack-plugin")

const config = {
    //mode设置webpack的运行的是一个开发环境
    mode:"development",
    //entry设置webpack的入口文件路径
    entry:path.join(__dirname,"./js/index.js"),
    //output设置webpack打包之后的新文件的文件名和存储路径
    output:{
        filename:"bundle.js",
        path:path.join(__dirname,"./dist"),
        publicPath:"./"
    },
    //module在打包过程中根据自己的需求载入第三方模块添加一些特色功能
    module:{
        rules:[
            {
                //匹配所有的js文件
                test:/\.js$/,
                //把node_modules文件夹下面的JS文件排除在JS转换功能以外
                exclude:/node_modules/,
                //当前配置的规则是babel-loader的规则
                loader:"babel-loader"
            }
        ]
    },
    //对打包功能本身添加额外的功能
    plugins:[
       //.......
        new CleanWebpackPlugin()
    ]
}

module.exports = config

使用webpack处理css

首先我们先明确,webpack本身只能处理JS,是不支持CSS执行的,所以我们会把CSS通过import导入到JS文件中来实现CSS的打包

import "./index.css";

webpack本身不能加载CSS代码,在JS里面也不能执行CSS代码,但是可以借助第三方loader来实现

安装loader
npm i css-loader style-loader -D

css-loader:负责解析导入到JS文件中的CSS样式

style-loader:在DOM中创建一个style,将css-loader负责解析的样式写入到style标签中的形成一个内部样式

配置
//我们把这个文件看成事一个webpack的配置文件,以后的webpack就使用这个配置文件
//webpack的配置文件里面,我们使用的事commonJS模块化规范

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin")
const {CleanWebpackPlugin} = require("clean-webpack-plugin")

const config = {
    //mode设置webpack的运行的是一个开发环境
    mode:"development",
    //entry设置webpack的入口文件路径
    entry:path.join(__dirname,"./js/index.js"),
    //output设置webpack打包之后的新文件的文件名和存储路径
    output:{
        filename:"bundle.js",
        path:path.join(__dirname,"./dist"),
        publicPath:"./"
    },
    //module在打包过程中根据自己的需求载入第三方模块添加一些特色功能
    module:{
        rules:[
            {
                //匹配所有的js文件
                test:/\.js$/,
                //把node_modules文件夹下面的JS文件排除在JS转换功能以外
                exclude:/node_modules/,
                //当前配置的规则是babel-loader的规则
                loader:"babel-loader"
            },
            {
                test:/\.css$/,
                use:[
                    "style-loader",
                    "css-loader"
                ]
            }
        ]
    },
    //对打包功能本身添加额外的功能
    plugins:[
        new HtmlWebpackPlugin({
            //配置模板文件的位置
            template:path.join(__dirname,"./index.html"),
            //生产的新文件的名称
            filename:"index.html",
            //生产的JS和CSS自动插入
            inject:true
        }),
        new CleanWebpackPlugin()
    ]
}

module.exports = config

当配置之后,我们还可以在package.json中去配置它的转换规则

"browserslist":[
    "last 2 versions",
    "> 1%",
    "ie 6"
  ]

注意:

这里写的其实跟我们在 .babelrc中配置的targets是一个东西,都是目标环境,只不过写在 .babelrc里面是针对babel做ES语法转换时使用的,不会影响到CSS

而写在package.json里面的是项目全局可用,并且写在不同位置会有优先级存在

我们也可以在项目的根目录下面专门新建一个叫做 .browserslistrc 文件专门用来配置目标环境

.browserslistrc 写法如下

# Browsers that we support

last 2 version
> 1%
not dead

使用postcss处理css的兼容性

安装第一个包

npm i postcss-loader -D

配置

{
    test:/\.css$/,
    use:[
        "style-loader",
        "css-loader",
        "postcss-loader"
    ]
}

当我们完成配置之后,我们会发现postcss并没有帮助我们解决css兼容性的问题,因为postcss只是提供了一个编译环境,在这个环境中要怎么编译需要做一个预设信息的配置,这些预设信息的配置我们通过postcss的插件来实现

postcss预设信息插件

1、postcss-import 如果在css里面发现了@import指令,进行处理

2、postcss-preset-env 提高css兼容性的插件,自动添加前缀,自动转换代码(以前我们使用的是postcss-cssnext已经被弃用了)

3、cssnano 可以对需要处理的css做进一步的压缩

npm i postcss-import postcss-preset-env cssnano -D
配置postcss的预设信息

在当前项目的根目录下新建一个文件postcss.config.js ,文件名必须是这个

module.exports = {
    plugins:[
        require("postcss-import"),
        require("postcss-preset-env"),
        require("cssnano")
    ]
}

注意:

如果在编译的时候报了true is not Postcss Plugin 因为postcss版本过低,我们要手动升级

npm i postcss@latest -D

重新分离css

在之前的步骤中,我们把css代码放入到JS里面通过postcss处理,提高了兼容性,但是我们还需要再次将这些分离成一个独立的css文件,这么我们才能在生产环境下使用,要完成这个目标我们使用webpack的插件 mini-css-extract-plugin

安装

npm i mini-css-extract-plugin -D

修改上面的配置规则,并调用css分离插件

//我们把这个文件看成事一个webpack的配置文件,以后的webpack就使用这个配置文件
//webpack的配置文件里面,我们使用的事commonJS模块化规范

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin")
const {CleanWebpackPlugin} = require("clean-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")

const config = {
    //mode设置webpack的运行的是一个开发环境
    mode:"development",
    //entry设置webpack的入口文件路径
    entry:path.join(__dirname,"./js/index.js"),
    //output设置webpack打包之后的新文件的文件名和存储路径
    output:{
        filename:"bundle.js",
        path:path.join(__dirname,"./dist"),
        publicPath:"./"
    },
    //module在打包过程中根据自己的需求载入第三方模块添加一些特色功能
    module:{
        rules:[
            {
                //匹配所有的js文件
                test:/\.js$/,
                //把node_modules文件夹下面的JS文件排除在JS转换功能以外
                exclude:/node_modules/,
                //当前配置的规则是babel-loader的规则
                loader:"babel-loader"
            },
            {
                test:/\.css$/,
                use:[
                    MiniCssExtractPlugin.loader,
                    {
                        loader:"css-loader",
                        options:{
                            importLoaders:1
                        }
                    },                   
                    "postcss-loader"
                ]
            }
        ]
    },
    //对打包功能本身添加额外的功能
    plugins:[
        new HtmlWebpackPlugin({
            //配置模板文件的位置
            template:path.join(__dirname,"./index.html"),
            //生产的新文件的名称
            filename:"index.html",
            //生产的JS和CSS自动插入
            inject:true
        }),
        new CleanWebpackPlugin(),
        new MiniCssExtractPlugin({
            filename:"css/index.[hash:8].css",
            ignoreOrder:false  //是否忽略第三方插件的处理
        })
    ]
}

module.exports = config

webpack文件处理

在css样式里面我们使用背景图片,字体文件等一些静态资源,那么在打包的时候针对这些文件需要怎么处理?现在我们使用的webpack5版本,其实5的版本已经可以自动对文件进行处理,但是处理效果很稀烂,所以我们还是依赖第三方包来实现

url-loader 用于处理路径

file-loader 用于处理文件,它会把涉及到文件拷贝到打包目录里面

安装包

npm i url-loader file-loader -D

配置

{
    test:/\.(jpe?g|png|gif|svg|bmp|webp)/,
    use:[
        {
            loader:"url-loader",
            options:{
                //只处理8Kb大小以内的
                limit:8 * 1024,
                name:"[name].[hash:8].[ext]",
                outputPath:"img/",
                esModule:false,
                publicPath:"../img"
            }
        }
    ],
    type:"javascript/auto"
}

注意:

在上面的处理过程中,我们发现我们并没有载入file-loader模块,但是文件依然处理成功,因为url-loader中有一个options叫做callBack,这个配置默认就是调用file-loader

webpack处理字体文件

处理字体和处理图片是一个原理

大部分情况下我们需要处理的都是图标字体,所以记得把图标字体的样式文件,在JS入口文件中导入

{
    test:/\.(ttf|eot|woff|woff2)$/,
    use:[
        {
            loader:"url-loader",
            options:{
                //只处理8Kb大小以内的
                limit:8 * 1024,
                name:"[name].[hash:8].[ext]",
                outputPath:"font/",
                esModule:false,
                publicPath:"../font"
            }
        }
    ],
    type:"javascript/auto"
}

按照上面的逻辑,我们可以认为,其他类型的静态资源文件,我们都可以按照这个逻辑来进行处理

配置打包进度条

因为打包的过程是非常缓慢的,所以打包过程中,会给人一种卡住的感觉,我们希望通过进度条的形式来表示我们的打包在正确执行中,所以我们会做一个进度条,来查看webpack的打包进度,这个时候我们需要一个插件来完成

安装插件

npm i progress-bar-webpack-plugin chalk@4 -D

chalk:是一个可以控制终端打印文字颜色的工具包,注意最新的5+的版本是不支持node导入的

progress-bar-webpack-plugin:可以显示webpack的打包进度条

const chalk = require("chalk");
const ProgressBarWebpackPlugin = require("progress-bar-webpack-plugin")


 plugins:[
        //......
        new ProgressBarWebpackPlugin({
            format:chalk.green("进度:") + chalk.white("[:bar]") + chalk.green(":percent"),
            clear:false
        })
    ]

至此我们的生产环境配置就算完成了(不包括对sass的配置),如果是打包生产环境的代码,需要把mode的值改成production

多页面配置

多页面配置其实就是要多设置几个入口文件作为打包入口,但是这样也意味着会生成多个打包文件,所以我们在自动将打包文件插入到html中的时候也需要对应多做几套配置,说明哪个打包文件插入到哪个html模板文件中

同时我们还可以对那么不需要打包的文件通过 copy-webpack-plugin 插件直接将这些文件拷贝到打包之后的文件夹中

安装插件

npm i copy-webpack-plugin -D

对配置文件做修改

//我们把这个文件看成事一个webpack的配置文件,以后的webpack就使用这个配置文件
//webpack的配置文件里面,我们使用的事commonJS模块化规范

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin")
const {CleanWebpackPlugin} = require("clean-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const chalk = require("chalk");
const ProgressBarWebpackPlugin = require("progress-bar-webpack-plugin")

const config = {
    //mode设置webpack的运行的是一个开发环境
    mode:"production",
    //entry设置webpack的入口文件路径
    entry:{
        index:path.join(__dirname,"./js/index.js"),
        login:path.join(__dirname,"./js/login.js")
    },
    //output设置webpack打包之后的新文件的文件名和存储路径
    output:{
        filename:"js/[name].[fullhash:8].js",
        path:path.join(__dirname,"./dist"),
        publicPath:"./"
    },
    //module在打包过程中根据自己的需求载入第三方模块添加一些特色功能
    module:{
        //......
    },
    //对打包功能本身添加额外的功能
    plugins:[
        new HtmlWebpackPlugin({
            //配置模板文件的位置
            template:path.join(__dirname,"./index.html"),
            //生产的新文件的名称
            filename:"index.html",
            //生产的JS和CSS自动插入
            inject:true,
            chunks:["index"]
        }),
        new HtmlWebpackPlugin({
            //配置模板文件的位置
            template:path.join(__dirname,"./login.html"),
            //生产的新文件的名称
            filename:"login.html",
            //生产的JS和CSS自动插入
            inject:true,
            chunks:["login"]
        }),
        new CleanWebpackPlugin(),
        new MiniCssExtractPlugin({
            filename:"css/index.[hash:8].css",
            ignoreOrder:false  //是否忽略第三方插件的处理
        }),
        new ProgressBarWebpackPlugin({
            format:chalk.green("进度:") + chalk.white("[:bar]") + chalk.green(":percent"),
            clear:false
        }),
        //不需要打包的文件通过以下插件来实现直接的copy
        new CopyWebpackPlugin({
            patterns:[
                {
                    from:path.join(__dirname,"./static"),
                    to:path.join(__dirname,"./dist/static")
                }
            ]
        })
    ]
}

module.exports = config

我们现在完成了一个多页面配置的生产环境下的webpack配置(不包含sass)

总结:

基于上面的一套webpack配置,我们制作了基于生产模式下的打包配置,但是,webpack的配置其实可以分为两套来看,一套针对生产环境,一套针对开发环境(测试),这两套环境下的配置代码90%都是相同的,不同点

1、开发环境下不需要分离css代码,所以不需要使用mini-css-extract-plugin这个插件,转而使用style-loader

2、开发环境下我们需要匹配值devServer

3、开发环境下不需要配置publicPath

开发环境配置

安装:热部署

npm i webpack-dev-server -D

新建一个webpack.config.dev.js

const path = require("path");  //路径处理
const HtmlWebpackPlugin = require("html-webpack-plugin");  //打包文件自动插入模板文件
const {CleanWebpackPlugin} = require("clean-webpack-plugin");  //自动清理打包之后的不需要的文件
const chalk = require("chalk");  //进度装饰
const ProgressBarWebpackPlugin = require("progress-bar-webpack-plugin"); //在终端中显示打包进度
const CopyWebpackPlugin = require("copy-webpack-plugin");  //把不需要打包的文件直接复制到打包目录中

const config = {
    mode:"development",
    entry:{
        index:"./js/index.js",
        login:"./js/login.js"
    },
    output:{
        filename:"./js/[name].[fullhash:8].js",
        path:path.join(__dirname,"./dist"),
        clean:true
    },
    module:{
        rules:[
            {
                test:/\.js$/,
                exclude:/node_modules/,
                loader:"babel-loader"
            },
            {
                test:/\.css$/,
                use:[
                    "style-loader",
                    {
                        loader:"css-loader",
                        options:{
                            importLoaders:1
                        }
                    },
                    "postcss-loader"
                ]
            },
            {
                test:/\.(jpe?g|png|gif|svg|bmp|webp)$/,
                use:[
                    {
                        loader:"url-loader",
                        options:{
                            limit:10 * 1024,
                            name:"[name].[hash:8].[ext]",
                            outputPath:"img/",
                            esModule:false
                        }
                    }
                ],
                type:"javascript/auto"
            },
            {
                test:/\.(ttf|eot|woff|woff2)$/,
                use:[
                    {
                        loader:"url-loader",
                        options:{
                            limit:10 * 1024,
                            name:"[name].[hash:8].[ext]",
                            outputPath:"font/",
                            esModule:false
                        }
                    }
                ],
                type:"javascript/auto"
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:path.join(__dirname,"./index.html"),
            filename:"index.html",
            inject:true,
            chunks:["index"]
        }),
        new HtmlWebpackPlugin({
            template:path.join(__dirname,"./login.html"),
            filename:"login.html",
            inject:true,
            chunks:["login"]
        }),
        new CleanWebpackPlugin(),
        new CopyWebpackPlugin({
            patterns:[
                {
                    from:path.join(__dirname,"./static"),
                    to:path.join(__dirname,"./dist/static")
                }
            ]
        }),
        new ProgressBarWebpackPlugin({
            format:chalk.green("进度:") + chalk.white("[:bar]") + chalk.green(":percent")
        })
    ],
    devServer:{
        port:8088,
        allowedHosts:"*",
        static:{
            directory:path.join(__dirname,"./static")
        },
        client:{
            overlay:true,
            progress:true
        },
        watchFiles:[
            "./index.html",
            "./login.html"
        ],
        hot:true
    }
}

module.exports = config

当我们配置好文件之后,我们在package.json中配置我们的启动脚本

"dev":"webpack-dev-server --config ./webpack.config.dev.js"

你可能感兴趣的:(vue,webpack,学习,前端,vue.js,javascript)