webpack的配置

安装

  1. npm i webpack webpack-cli

    第一个是webpakc工具 第二个是webpack的指令工具 可通过在终端上输入指令来操纵webpakc帮助对项目进行处理.

webpack概念

  1. loader

    webpack只可以对js文件和json文件进行处理,对其它格式文件不能处理,需要loader对其先进行处理之后,才能交由webpack处理.

webpack指令

  1. 运行指令

    • webpack "entry路径" -o "output路径" --mode=development/production

    该命令会将入口路径的文件打包到出口路径的文件,并指令环境为开发环境.

    打包后会输出一个hash值可以用来唯一标识这次打包文件的id,以及一些其它额外信息,如打包的时间,以及大小等.

  • 开发环境和生产环境所做的事可以将es6的模块化转化为浏览器可识别的模块化,生产环境会比开发环境对一个压缩代码.

webpack.config.js

  1. 文件的意义

    自己在项目的根目录下创建这个文件,且名字只能是这个,然后可在这里写配置,使得webpack可通过这里的配置对项目进行管理.

    注意点:构建工具都是基于node环境下的,也就是说只能使用commonjs的规范来导入导出模块.

  2. 文件的基本配置

const path =require("path")
module.exports={
    //入口文件 需要将所有依赖的文件最后都通过直接或间接的方式 最终放到这个文件里
    entry:"./src/index.js",
    // 出口文件
    output:{
        filename:"build2.js",
        path:path.join(__dirname,'build')
    },
    // 配置loader 即让webpack可对其它非js文件以及json文件处理
    module:{
        //每一个规则对应一种文件的处理
        rules:[

        ]
    },

    //配置插件,可让webpack做更多事
    plugins:[],
    //配置环境 有development 和production
    mode:"development"

}
样式文件的处理
module:{
        //每一个规则对应一种文件的处理
        rules:[
            {
                test:/\.css$/,
                // use使用的包是从右向左,从下网上执行 
                use:[
                    "style-loader", //创建一个style标签, 并将其放入head标签里,将转化为字符串的css样式放入这里.
                    "css-loader"  //将css文件转化为js的字符串
                ]
            },
            {
                test:/\.less$/,
                use:[
                    "style-loader",
                    "css-loader",
                    "less-loader"  //将less转化为css
                ]
            }
        ]
    }
html文件的处理

html文件可通过插件处理

//该插件需要导入 由于需要调用插件的构造函数来处理.
const webPackPlugin=require("html-webpack-plugin")
plugins:[
        new webPackPlugin({
          //文件打包后将自动处理并输出到一个index.html文件里,此文件与打包的文件同一级目录,而那个index.html以这个html文件为模板,只是多了一个引入.
            template:"./src/template.html",
            //压缩html代码
            minify:{
                collapseWhitespace:true,
                removeComments:true
            }
        })
    ]
图片资源的打包

样式文件的图片背景图片需通过url-loader处理,不过该loader依赖file-loader所以两个都要下,而html里的图片则需要html-loader辅助url-loader进行处理.

module:{
        //每一个规则对应一种文件的处理
        rules:[
            {   
                //对图片的处理 根据样式文件的引入图片的路径可通过下面这个loader进行处理,不过如果是处理图片的话该loader还需要依赖一个file-loader. 
                test:/\.(jpg|png|jpeg)$/,
                loader:"url-loader",   //如果只需要一个插件 可使用loader属性.

                //options是对插件的配置 ,这里的limit是对文件大小的配置,如果图片小于14Kb则已base64处理,会生成一个图片的字符串,不需要产生新文件即可引入. 超过的还需要生成一个新文件.文件名根据图片内容产生的hash值.
                options:{
                    limit:14*1024,
                    esModule:false  //由于html-loader使用的是commonjs引入 ,所以需将es引入关闭,避免冲突.
                }
            },
            //需要注意的是,如果html标签里直接引入的文件,需要html-loader先进行处理,由于html不会将文件输出到js里,所以先将html文件引入的文件,交由url-loader在处理.
            {
                test:/\.html$/,
                loader:"html-loader"
            }
        ]
    }
其它资源打包
                    {   
                //表示除了这些文件 其它都用下面的loader.
                exclude:/\.(png|jpg|jpeg|js|html|json|less|css|ts)/,
                loader:"file-loader"
            }
使用devServer

使用devserver可让webpack在内存中进行打包编译,并且会根据文件的变化来自动编译.

是webpack下的一个额外的配置项.

要使用这个配置,依赖一个webpack-dev-server的指令包,且需要通过npx 运行.

为npx webpack-dev-server

devServer:{
        contentBase:path.join(__dirname,'build'),  //路径
        open:true, //自动打开默认浏览器
        port:3000, //指定端口
        compress:true, //压缩代码,
            quiet:true, //指示启动时其它额外信息不要显示
          //配置开发环境下的跨域问题 当想向其它服务器请求东西的时候,可通过前端路由所在的端口向其它域发送请求 .
        proxy:{
          '/api':{
            //当访问/api/xxx路径时,可将请求转给自己的服务器,让自己的服务器在去访问下面的路径
            target:'http://localhost:3000',
              pathRewrite:{
                '^api/':'' //将api去掉
              }
          }
        }
    }
打包输出目录的配置

默认所有文件除了引入到js文件里的样式被特殊处理外,其它资源文件也都会输出到出口文件,这样不利于查看.

若想让打包文件目录结构更清晰,可以指定输出目录. 但所有文件依然会输出出口文件里只是分配一个文件夹.

  • 对于总的js文件 可以在filename的前面加入路径 如: "js/filename",
    • 对于其它资源问价 可在module的每种文件的配置项里options选项里添加outputPath ,如outputPath:'img' 即可输出到出口文件里的img文件夹下.
生产环境的特殊处理

开发环境下只需要代码可以运行,测试代码.并不需要对代码的执行速度,兼容性有要求.

  • 问题:

    1. 生产环境下需要对代码进行特殊处理,由于之前都是将css代码以字符串的形式放入到js里,在由js将样式插入到标签里,可能导致页面加载很慢,以及出现闪屏的现象

    2. 打包后的js等代码需要进行压缩处理.

  • 解决办法

    1. 下载一个mini-css-extract-plugin来,并对其进行配置后,然后用它代替style-loader,由于style-loader只能将js里的样式引入到head里,但还是和js在一起.
 用miniCssExtractPlugin.loader来取代style-loader,由于该loader可以生产css文件,

 且在下面的插件里将其配置的filename用路径添上,可以使得有一个css文件夹.

 ```javascript
 const miniCssExtractPlugin=require('mini-css-extract-plugin')
 module:{
         //每一个规则对应一种文件的处理
         rules:[
             {
                 test:/\.css$/,
                 // use使用的包是从右向左,从下网上执行 
                 use:[
                     //"style-loader", //创建一个style标签, 并将其放入head标签里,将转化为字符串的css样式放入这里.
                     miniCssExtractPlugin.loader,
                     "css-loader"  //将css文件转化为js的字符串
                 ]
             },
             {
                 test:/\.less$/,
                 use:[
                     // "style-loader",
                     miniCssExtractPlugin.loader,
                     "css-loader",
                     "less-loader"  //将less转化为css
                 ]
             }
             
         ]
     },
  plugins:[
         new miniCssExtractPlugin({
             filename:"css/index.css"
         })
     ],
 ```
  1. 压缩css

    依赖的包(插件) optimize-css-assets-webpack-plugin

    只需要引入 再在插件出new使用即可

css兼容性的处理

为了让写的css样式可以兼容大部分浏览器,需要对其做一些处理.

需要依赖两个包,一个是postcss-loader 可以对css的兼容性样式进行处理,而postcss-preset-env,可以找到项目下的package.json下的浏览器配置,可对指定的浏览器以及根据当前所处的环境对css样式进行兼容配置

//webpack.config.json
module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
            //use可以使用多个插件,但是如果某个插件还需要单独配置,可用{}将其阔气来,然后通过options进行配置
                        {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: () => [
                // postcss的插件
                require('postcss-preset-env')()
              ]
            }
         }]
      }

//package.json
//process可以获取电脑的环境变量  打包的时候默认以生产环境配置 这个可以指定当前是开发环境
"browserslist": {
              // 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development
              "development": [
                "last 1 chrome version",
                "last 1 firefox version",
                "last 1 safari version"
              ],
              // 生产环境:默认是看生产环境
              "production": [
                ">0.2%",
                "not dead",
                "not op_mini all"
              ]
            }
js文件的兼容

需要用到babel-loar对其进行处理, 然而这个插件又依赖babel,@babel/core,

可使用@babel/preset-env对js代码做简单的兼容,若需要兼容更多,又需要下载core-js

{
                test:/\.js$/,
                // 需要将这个文件jia下的代码给去除
                exclude:/node_modules/,
                loader:"babel-loader",
                options:{
                    presets:[
                        [
                            //可对js代码做简单的检查
                            '@babel/preset-env',
                            {
                              // 按需加载
                              useBuiltIns: 'usage',
                              // 指定core-js版本 检查比较大
                              corejs: {
                                version: 3
                              },
                              // 指定兼容性做到哪个版本浏览器
                              targets: {
                                chrome: '60',
                                firefox: '60',
                                ie: '9',
                                safari: '10',
                                edge: '17'
                              }
                            }
                          ]
                ]}
                        
                   

            },

性能优化

  1. 开发优化
    • 热模块替换 (hmr)

      即让模块在打包的时候,如果某个模块变了,只对那个单独的文件做替换,其它不变.

 ```javascript
 devServer:{
         contentBase:path.join(__dirname,'build'),  //路径
         open:true, //自动打开默认浏览器
         port:3000, //指定端口
         compress:true, //压缩代码
         hot:true
     }
 ```

 可在webpack的内存加载中加入Hot:true即可热模块替换,但是只是会对css起效,对js以及html不起效.html不需要单独配置,由于html只有一个模块变化了肯定要变,

 js 可以在入口文件的js处加上进行处理.

 ```javascript
 if(module.hot){
   module.hot.accept('模块文件',回调函数)
 }
 ```
  • 代码调试

默认的时候,如果打包的时候代码出错,由于所有文件都打包到一起,所以很难找到出错的位置,

在配置的根目录下进行devtool配置可解决问题.

值都不一定 source-map虽然慢 但是可以定位到行,而eval不可以

devtool:'eval-source-map' //开发调试 执行快 产生的代码块和源文件的映射直接写在打包的代码里
//devtool:'source-map'//生产调试 执行稍慢 产生的代码块单独用一个文件存放
  1. 开发和生产通用
    • 加快打包速率之oneOf

    通过oneOf包裹,默认rules里放的是每一个对象规则,但是默认的规则是 比如css文件自己通过某个loader处理完之后,还要继续往下找看是否还有处理css的loader,如果有则更好,没有显然浪费了时间,所以为了节省时间,如果知道某些文件只需要通过一组loader处理,则可以写在oneOf里,这样对应的文件处理完之后,则不在处理.

    需要注意的是如果一种文件需要几组loader处理,则不能将几组loader都写在oneOf里 不然可能值处理了一组

module:{
        //每一个规则对应一种文件的处理
        rules:[
            //默认rules里放的是每一个对象规则,但是默认的规则是 比如css文件自己通过某个loader处理完之后,还要继续往下找看是否还有处理css的loader,如果有则更好,没有显然浪费了时间,所以为了节省时间,如果知道某些文件只需要通过一组loader处理,则可以写在oneOf里,这样对应的文件处理完之后,则不在处理.

            // 需要注意的是如果一种文件需要几组loader处理,则不能将几组loader都写在oneOf里 不然可能值处理了一组
            {oneOf:[
                {
                    test:/\.css$/,
                    // use使用的包是从右向左,从下网上执行 
                    use:[
                        //"style-loader", //创建一个style标签, 并将其放入head标签里,将转化为字符串的css样式放入这里.
                        miniCssExtractPlugin.loader,
                        "css-loader", //将css文件转化为js的字符串
                        {
                            loader: 'postcss-loader',
                            options: {
                              ident: 'postcss',
                              plugins: () => [
                                // postcss的插件
                                require('postcss-preset-env')()
                              ]
                            }
                          }
                    ]
            
                },
                {
                    test:/\.less$/,
                    use:[
                        // "style-loader",
                        miniCssExtractPlugin.loader,
                        "css-loader",
                        {
                            loader: 'postcss-loader',
                            options: {
                              ident: 'postcss',
                              plugins: () => [
                                // postcss的插件
                                require('postcss-preset-env')()
                              ]
                            }
                          },
                        "less-loader"  //将less转化为css
                    ]
                },
                {   
                    //对图片的处理 根据样式文件的引入图片的路径可通过下面这个loader进行处理,不过如果是处理图片的话该loader还需要依赖一个file-loader. 
                    test:/\.(jpg|png|jpeg)$/,
                    loader:"url-loader",   //如果只需要一个插件 可使用loader属性.
    
                    //options是对插件的配置 ,这里的limit是对文件大小的配置,如果图片小于14Kb则已base64处理,会生成一个图片的字符串,不需要产生新文件即可引入. 超过的还需要生成一个新文件.文件名根据图片内容产生的hash值.
                    options:{
                        limit:14*1024,
                        esModule:false , //由于html-loader使用的是commonjs引入 ,所以需将es引入关闭,避免冲突.
                        outputPath:'img'
                    },
                    
                },
                //需要注意的是,如果html标签里直接引入的文件,需要html-loader先进行处理,由于html不会将文件输出到js里,所以先将html文件引入的文件,交由url-loader在处理.
                {
                    test:/\.html$/,
                    loader:"html-loader"
                },
                // {
                //     //若有eslint,需要加
                //     // enfore:'pre' 来保证其优先执行
                // }
                //处理js的兼容性问题
                {
                    test:/\.js$/,
                    // 需要将这个文件夹下的代码给去除
                    exclude:/node_modules/,
                    loader:"babel-loader",
                    options:{
                        presets:[
                            [
                                //可对js代码做简单的检查
                                '@babel/preset-env',
                                {
                                  // 按需加载
                                  useBuiltIns: 'usage',
                                  // 指定core-js版本 检查比较大
                                  corejs: {
                                    version: 3
                                  },
                                  // 指定兼容性做到哪个版本浏览器
                                  targets: {
                                    chrome: '60',
                                    firefox: '60',
                                    ie: '9',
                                    safari: '10',
                                    edge: '17'
                                  }
                                }
                              ]
                    ]}
                            
                       
    
                },
                {   
                    //表示除了这些文件 其它都用下面的loader.
                    exclude:/\.(png|jpg|jpeg|js|html|json|less|css|ts)/,
                    loader:"file-loader",
                    options:{
                        outputPath:'fontimg'
                    }
                }
            
            ]
            
            }, 
            
        ]
    }

  • 缓存处理

    • babel

    由于在生产环境下没有hmr 但是babel进行处理的时候 每次都会对模块进行转化,显然每次都这样处理不是很好.

    设置 cacheDirectory:true

    {
                            test: /\.js$/,
                            // 需要将这个文件夹下的代码给去除
                            exclude: /node_modules/,
                            loader: "babel-loader",
                            options: {
                                presets: [
                                    [
                                        //可对js代码做简单的检查
                                        '@babel/preset-env',
                                        {
                                            // 按需加载
                                            useBuiltIns: 'usage',
                                            // 指定core-js版本 检查比较大
                                            corejs: {
                                                version: 3
                                            },
                                            // 指定兼容性做到哪个版本浏览器
                                            targets: {
                                                chrome: '60',
                                                firefox: '60',
                                                ie: '9',
                                                safari: '10',
                                                edge: '17'
                                            }
                                        }
                                    ]
                                ],
                                //第二次会读取缓存
                                cacheDirectory:true,
    
                            }
    
    
    
                        }
    
    • 服务器强制缓存

      由于用户访问服务器的时候,(是服务器,要通过域名ip地址访问),浏览器会强制将服务器的资源进行缓存一段时间,此时若服务器想修改一些代码,由于浏览器有缓存的东西,所以不会更新.

      解决办法,每次打包的时候,文件名后面加上hash值,那么只要改东西,hash值就会变,浏览器检查到新的资源必然会进行加载.

      但是这样写有一个问题,由于一开始合并文件的时候css和js都合并到一个chunk,所以css的hash值和js的hash值是一样的,所以当只改变一个文件的时候,hash都变,所以重新请求的时候两个文件都要重新请求,即使之改变了一个.

      output: {
              filename: "js/4打包其它资源.[hash:10].js",
              path: path.join(__dirname, 'build')
          },
       plugins: [
             
              //处理css,指定到输出目录
              new miniCssExtractPlugin({
                  filename: "css/index.[hash:10].css"
              }),
           
          ],
      

      所以为了区分

      做了一些修改 只根据文件内容的hash来取名

      output: {
              filename: "js/4打包其它资源.[contenthash:10].js",
              path: path.join(__dirname, 'build')
          },
       plugins: [
             
              //处理css,指定到输出目录
              new miniCssExtractPlugin({
                  filename: "css/index.[contenthash:10].css"
              }),
           
          ],
      
tree shaking

将没有用到的代码可去除掉

使用条件 mode需开启为production 且模块之间的导入是以es6的导入方式

注意事项:需要在package.json目录配置不需要去除掉的代码

不然可能会将这些文件误删

"sideEffects":["*.css","*.less"]
split chunk

根目录配置该 优化可以将node_module里打包的代码和其它代码分开,且可让多入口的文件都同时依赖一个node_modules打包的代码.

默认情况下 无论开发还是依赖,多个js文件同时依赖某个node_moduls这个文件也只会打包一次,不会多次打包.

optimization:{
        splitChunks:{
            chunks:'all'
        }
    }

如果不是多入口,但是某些js文件也需要和其它js代码分割,那么可在导入的时候进行处理即可

//导入的时候
//注意的是这里的注释有用 指定分离后的名字 返回一个promise 在then里调用 导出的函数
import(/*webpackChunkName:'test'*/'路径').then(({那个路径下的东西解构值})=>{
  )
lazy-load(js文件的懒加载)

配合上面的js分离,可对某些js文件懒加载

//如

//这样即可对这个文件懒加载
document.querySelector('.class').onclick=function(){
    import(/*webpackChunkName:'test'*/'路径').then(({那个路径下的东西解构值})=>{
    )
}

预加载

//正常加载都是一个个加载,预加载则是一开始不加载等到其它资源加载完毕,浏览器空闲了,在加载这个. (慎用 有兼容问题)
document.querySelector('.class').onclick=function(){
    import(/*webpackChunkName:'test',webpackPrefetch:true*/'路径').then(({那个路径下的东西解构值})=>{
    )
}
pwd(渐进式网络开发应用)

依赖 workbox-webpack-plugin

externals

打包的时候忽略某个node_module下导入的包

可在html 用script 标签引入 cdn方式. 这样项目还是照常运行

externals:{
        jquery:"jquery"
    }
dll

对node_modules导入的文件都进行单独打包

详细配置

都是相对于根配置

entry
  • 值有三种类型 String,Array,Object.

    string若output没写filename则会打包成main.js,只会打包成一个文件

    Array 多入口 也只会打包成一个文件,可将htmL放进来,可开启html的hmr.

    Object 多入口 多出口 出口名为键 {键:"文件路径"},需要output的filename改为

    '[name].js'

    每个键后面还可以跟数组 ,将这些文件打包成一个js

output
output: {
        filename: "js/4打包其它资源.[contenthash:10].js",
        path: path.join(__dirname, 'build'),
        // publicPath:"/"  所以资源引入的路径前缀 打包后再资源引入的前面加上/ 上线的时候使用,
        // chunkFilename:"" 用于非入口文件的chunk的名字 就是有些文件最后也会生产一个文件 以这个来命名,
        library:'[name]' //name是前面entry定义的键如果没定义就是main,因为默认output输出main  library可将打包后的整个文件通过name这个变量暴露出去,使得其他东西可以访问.
    libraryTarget:'window'//客户端 绑定给window对象
    },
resolve

和路径有关

//解析模块的规则
resolve:{
  //配置路径别名
  alias:{
    别名:"路径"
  },
   //配置省略文件路径的后缀名 默认有js和json
   extensions:['.css','.less','vue'],
   //告诉webpack找模块在哪个目录找 node_modules 
   modules:[]
}
optimization

只在生产环境下起效

optimization:{
   splitChunks:{
     chunks:'all',
     minSize:30*1024,  //指定分割的chunk最小为30kb
     maxSize:0, //意思最大没有限制
     minChunks:1,  //要提取的chunk最少被引用一次
     
   },
   //当打包的时候会多出一个runtime模块,由于将入口文件和node_moudles文件分离,以及其它模块分离,若其它模块分离,又希望其它文件不变,但是由于入口文件时通过hash值记录的其它文件的依赖关系,其它文件变了,必然导致其它文件的hash值变化,也就导致入口文件变了,所以对引入的模块的hash值特别处理,这样哪个文件变化了,只改变那个模块以及对应hash值文件.
   runtimeChunk:{
     name:entrypoint=>`runtime-${entrypoint.name}`
   },
   minimizer:[
     //配置生产环境的压缩方案: js和css
     //webpack在4.26以上生产环境不再使用uglify压缩代码 由于其不再维护,使用terser来压缩
     //需下这个包 才可以进行配置
     new TerserWebpackPlugin({
       //开启缓存
       cache:true,
       parallel:true, //开启多进程
       
     })
   ]
}

你可能感兴趣的:(webpack的配置)