webpack极速入门

215 阅读8分钟

webpack五个核心概念

1 entry
2 output
3 loader
4 plugins
5 mode
6 *devServer uTools_1650896794514.png

webpack初体验

1 安装 webpack

npm init
npm i webpack@4.41.6 webpack-cli@3.3.11\

开发环境打包:(以/src/index.js为入口文件)

webpack ./src/index.js -o ./build/built.js --mode=development\

生产环境打包:(以/src/index.js为入口文件)

webpack ./src/index.js -o ./build/built.js --mode=production 注意如果报错可以这样

uTools_1651063530174.png

uTools_1651063530174.png uTools_1650877361698.png

uTools_1650877383581.png 然后 npm run ss即可

总结

1.webpack能处理js\json,不能处理css\img等资源. 2.生产环境和开发环境将es6模块化编译成浏览器能识别的模块化
3.生产环境比开发环境多一个压缩js代码

打包css样式资源

webpack.config.js
作用 指示webpack干那些活(运行webpack命令时会加载里面的配置)
所有构建工具都是基于nodejs平台运行的 模块化采用commonjs**** webpack.config.js
npm i css-loader@5
npm i style-loader@1
npm i less-loader@5
npm i less@3

//webpack。config。js
const  { resolve }=require('path');

//webpack配置文件

//不同文件用不同loader处理

module.exports={

    //入口文件
    entry:'./src/index.js',
    //输出
    output:{
        //输出文件名
        filename:'built.js',
        //输出路径
            // __dirname nodejs变量 代表当前文件所在文件夹的绝对路径
        path:resolve(__dirname,'build')      
    },
    //loader的配置
     module:{
            rules:[
                //详细的loader配置
                {
                    //匹配那些文件
                    test:/\.less$/,
                    //使用那些loader进行处理
                    use:[ //use数组中loader执行顺序:从左到右从上到下依次执行
                        //创建style标签将js中的样式文件插入进行 添加到head中生效
                        'style-loader',
                        //将css变更成commonjs模块加载js中,里面是样式字符串
                        'css-loader',
                        //'less-loader', 将less编译为css
                    ]
                }
            ]
        },
    //plugins配置
    plugins:[],
    mode:'development'
    //mode:'production'

}

打包html资源

loader 1下载 2使用(配置loader)
piugins 1下载 2引入 3使用
下载 npm i html-webpack-plugin@3
在文件开头的引入 const HtmlWebpackPlugin = require('html-webpack-plugin')
使用

    plugins:[
    //plugins的配置
    //html-webpack-plugin
    //功能:默认会创建空的html自带引入打包输出的css和js
    new HtmlWebpackPlugin(
       { //复制'./src/index.html'文件内容并自带引入打包输出的css和js
          template:'./src/index.html'
       }
    )
    ]

打包图片资源

loader 1下载 2使用(配置loader) 下载 url-loader@3和 file-loader@5
npm i url-loader@3 file-loader@5
这种方式处理不了html中的图片,如image标签的图片就处理不了 安装html-loader处理html中的图片

module:{
            rules:[
                //详细的loader配置
                {
                    //匹配那些文件
                    test:/\.css$/,
                    //使用那些loader进行处理
                    use:[ //use数组中loader执行顺序:从左到右从上到下依次执行
                        //创建style标签将js中的样式文件插入进行 添加到head中生效
                        'style-loader',
                        //将css变更成commonjs模块加载js中,里面是样式字符串
                        'css-loader',
                        //'less-loader', 将less编译为css
                    ]
                },
                //处理图片资源
                {  //这种方式处理不了html中的图片,如image标签的图片就处理不了
                   test:/\.(jpg|png|gif)$/,
                   // use:['url-loader'] 多个loader用use数组配置,单个可以loader:'url-loader'
                   loader:'url-loader',
                   options:{
                       //图片小于8kb,就会被base64处理
                       //base64优点:减少请求数量(减轻服务器压力)
                       //base64缺点:图片体积会更大(文件请求速度更慢)
                       limit:8 * 1024

                   }

                }

            ]

        }

安装html-loader
npm i html-loader@0.5

module: {
        rules: [
            //详细的loader配置
            {
             。。。。。。
            //处理图片资源
            { //这种方式处理不了html中的图片,如image标签的图片就处理不了
                test: /\.(jpg|png|gif)$/,
                // use:['url-loader'] 多个loader用use数组配置,单个可以loader:'url-loader'
                loader: 'url-loader',
                options: {
                    //图片小于8kb,就会被base64处理
                    //base64优点:减少请求数量(减轻服务器压力)
                    //base64缺点:图片体积会更大(文件请求速度更慢
                    limit: 8 * 1024,
                   /* 问题:url-loader默认使用es6模块化解析,
                      而html-loader引入图片是commonjs,
                      所以解析时会出问题 解析后的引入图片的url本来是
                      /xxx./xsda.png 结果成为[object Module]
                      解决:关闭url-loader的es6模块化,使用commonjs解析
                    */
                    esModule:false,
                    //如果不想图片名字太长可以以下操作
                    //[hash:10] 取图片哈希的前十位
                    //[ext] 取文件原来的拓展名
                    name:'[hash:10].[ext]'
                }
            }, {
               test: /\.html$/,
                //处理html文件的img图片,(负责引入img,从而
                //能被url-loader进行处理)
                loader: 'html-loader',
            }
        ]
    },

打包其他资源

注意除了css js html 以外的资源 此时包含了图片文件 exclude:/.(css|js|html)$/

要想不包含图片文件 exclude:/.(css|js|html|jpg|png|gif)$/,

module: {
        rules: [
            {
            .......
            },
            {//除了css js html jpg png gif以外的资源
                exclude:/\.(css|js|html|jpg|png|gif)$/,
                loader:'file-loader',
                options:{
                    name:'[hash:10].[ext]'
                }
            }
         ]

devServer(热加载)

安装devServer npm i webpack-dev-server@3 运行 npx webpack-dev-server

写在mode:'xxasdas',后
//开发服务器 用来自动化(自动编译,自动打开浏览器,自动刷新浏览器)
    //特点:只会在内存中打包
    devServer:{
        contentBase: resolve(__dirname, 'build'),
        //启动gzip压缩
        compress:true,
        //端口号
        port:4000
    }
}

在浏览器用 http://localhost:xxxx/ 访问devServer

开发环境配置

打包命令直接 webpack 注意 如果报错 在package.json如下设置然后npm run saa效果等同于直接 webpack
uTools_1650943165620.png 可以设置各个类型资源的的输出目录 js直接在

output{
    ...,
    //设置js文件输出到那个目录
    filename:'xx/xx/x/xxx.js',
    ...,
}


其他类型资源在(css资源不需要设置因为css加入到了js文件中)

options:{
    ...,
    //在jmgs文件夹下输出图片
    outputPath:'imgs'
    ...,
}

构建环境介绍

提前css成单独文件

注意 此处如果css引入了图片等填写有路径的 打包后会报错 后文会解决
下载
npm i mini-css-extract-plugin
引入
const MiniCssExtractPlugin= require('mini-css-extract-plugin')
使用(要plugins和loader上同时注册)
plugins

    plugins: [ //plugins的配置
        //html-webpack-plugin
        //功能:默认会创建空的html 自带引入打包输出的css和js
        new HtmlWebpackPlugin({ //复制 './src/index.html' 文件内容并自带引入打包输出的css和js
            template: './src/index.html'
        }),
        //注册
        new MiniCssExtractPlugin({  
        //指定文件与指定路径
            filename:'css/xxx.css'
            })
    ],

loader
注意style-loader和MiniCssExtractPlugin.loader不共用
style-loader:创建style标签将js中的样式文件插入进行 添加到head中生效
MiniCssExtractPlugin.loader:提前js中css成单独文件 所以不需要创建style标签即不用使用style-loader

{                //匹配那些文件
                test: /\.css$/,
                //使用那些loader进行处理
                use: [ //use数组中loader执行顺序:从左到右从上到下依次执行
                    //创建style标签将js中的样式文件插入进行 添加到head中生效
                    //'style-loader',  
                    //注册
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                   
                ],
            },

对输出css文件重命名与指定输出路径

new MiniCssExtractPlugin({
           //指定文件与指定路径
            filename:'css/xxx.css'
        })

css的兼容性处理

需要postcss-loader和postcss-preset-env
安装 npm i postcss-loader@3 postcss-preset-env@6
引入loader

                test: /\.css$/,
                //使用那些loader进行处理
                use: [ //use数组中loader执行顺序:从左到右从上到下依次执行
                    //创建style标签将js中的样式文件插入进行 添加到head中生效
                    //'style-loader',
                    //将css变更成commonjs模块加载js中,里面是样式字符串
                    MiniCssExtractPlugin.loader,
                   'css-loader',
                    //'less-loader', 将less编译为css
                    {  //帮助postcss找到package.json中的browserslist里面的配置,
                        //通过配置加载指定的css兼容性样式
                        loader:'postcss-loader',
                       options:{
                          ident:'postcss',
                            plugins:()=>[
                                require('postcss-preset-env')()
                            ]  
                        }
                    },
                ],

配置package.json中的browserslist

"browserslist":{
//开发环境--》设置node环境变量 在webpack。config。js文件头部写 porcess.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"
    ]
  },

压缩css

安装插件 npm i optimize-css-assets-webpack-plugin@5
引入插件 const OptimizeCssAssetsWebpackPlugin= require('optimize-css-assets-webpack-plugin')
plugins中引入

plugins:[
    new  OptimizeCssAssetsWebpackPlugin()
]

js语法检查eslint

安装eslint-loader eslint
npm i eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import
在webpack引入

uTools_1651047327775.png

    {
        test:/\.js$/,
        //不语法检查node_modules下js
        exclude:/node_modules/,
        loader:'eslint-loader',
        options:{
        //自动修错误
            fix:true
        }
        
    }

只检测自己写的js代码 第三方库的不经常
设置检查规则:
在package.json中设置 airbnb规则

    "eslintConfig":{
        "extends:"airbnb-base"
    }

要想不检查某一行代码可以在这一行代码的上一行加入此//eslint-disable-next-line注释

js兼容性处理eslint

babel-loader @babel/preset-env 问题:只能转换基本语法 如promise就不能转化 要想解决 需要再安装@babel/polyfillnpm i babel/polyfill
安装
npm i babel-loader@8 @babel/preset-env@7
npm i @babel/core
引入

{
    test:/\.js$/,
    exclude:/node_modules/,
    loader:'babel-loader',
    options:{
    //预设:指示babel做怎么邀的兼容性处理
       presets:['@babel/preset-env'] 
    }
}

解决只能转换基本语法的问题

问题:只能转换基本语法 如promise就不能转化
要想解决 需要再安装@babel/polyfillnpm i @babel/polyfill@7
再需要转换的js文件头引入import '@babel/polyfill';(缺点会将所有兼容性代码引入体积太大了)

终极解决方案:————按需引入兼容性代码(使用此方案不引入import ' @babel/polyfill ' )

安装npm i core-js@3

{
    test:/\.js$/,
    exclude:/node_modules/,
    loader:'babel-loader',
    options:{
    //预设:指示babel做怎么邀的兼容性处理
       presets:[
       '@babel/preset-env',
       //按需加载
       {
           useBuiltIns:'usage',
           //指定core-js版本
           corejs:{
               version: 3
           },
           //指定浏览器做到兼容那个版本的浏览器
           targets:{
               'chrome':'60',
               fireforx:'60',
               ie:'9',
               safari:'10',
               edge:'17'
       }
       ] 
    }
}

压缩html和js

js压缩

生产环境会自动压缩 把mode调成生产环境
mode:"porduction"

html压缩

在plugins下

 plugins:[
    //plugins的配置
    //html-webpack-plugin
    //功能:默认会创建空的html自带引入打包输出的css和js
    new HtmlWebpackPlugin(
           { //复制'./src/index.html'文件内容并自带引入打包输出的css和js
          template:'./src/index.html',
          //压缩的配置项
          minify:{
          //移除空格
          collapseWhitespace:true,
          //移除注释
          removeComments:true,
          }
       }
    )
    ]

生产环境基本配置

当一个文件要被多个loader处理 一定要处理好loader顺序 先语法检查 在兼容性 enforce:'pre' //优先执行 uTools_1650961532778.png

const {resolve}  = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const HtmlWebpackPlugin  = require('html-webpack-plugin')


module.exports = {
    //入口文件
    entry:"./src/js/index.js",
    // 输出地址
    output:{
        filename:"js/built.js",
        path:resolve(__dirname,'build')
    },
    //loader
    module:{
        rules:[
            // 打包css
               {
                test:/\.css$/,
                use:[
                    //提取css
                    MiniCssExtractPlugin.loader,
                    // 将 css 文件整合到 js 文件中
                    'css-loader',
                   //修改loader的默认配置需要写成对象的形式
                    {
                        //设置加载器
                       loader:'postcss-loader',
                       //配置options
                       options:{
                           postcssOptions:{
                               //插件
                               plugins:[
                                  [
                                  	//指定环境
                                   "postcss-preset-env",
                                   {
                                       browsers:'last 2 versions'
                                   }
                                  ]
                               ]
                           }
                       }
                    }
                ]
            },
            {
                //打包less
                test:/\.less$/,
                use:[
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    //修改loader的默认配置需要写成对象的形式
                    {
                        //设置加载器
                       loader:'postcss-loader',
                       //配置options
                       options:{
                           postcssOptions:{
                               //插件
                               plugins:[
                                   [
                                   //指定环境
                                   "postcss-preset-env",
                                   {
                                       browsers:'last 2 versions'
                                   }
                                   ]
                               ]
                           }
                       }
                    },
                    'less-loader'
                ]
            },
            {
                //eslint
                test:/\.js$/,
                exclude:/node_module/,
                loader:'eslint-loader',
                // 优先执行
                enforce: 'pre',
                options:{
                    fix:true
                }
            },
            {
                test:/\.js$/,
                exclude:/node_module/,
                loader:'babel-loader',
                options:{
                    // 预设:指示 babel 做怎么样的兼容性处理
                    presets:[
                        [
                            '@babel/preset-env',
                            {
                                //按需加载
                                useBuiltIns:'usage',
                                //指定core-js版本
                                corejs:{
                                    verson:2
                                },
                                // 指定兼容性做到哪个版本浏览器
                                targets: { 
                                    chrome: '60',
                                    firefox: '60',
                                    ie: '9',
                                    safari: '10',
                                    edge: '17'
                                }
                            }

                        ]
                    ]
                }
            },
            {
                //打包图片
                test:/\.(jpg|png|gif|webp)$/,
                loader:'url-loader',
                options:{
                    limit: 8*1024,
                    name:'[hash:10].[ext]',
                    outputPath:'imgs',   
                    esModule:false             
                }
            },
            //处理html下的图片
            {
                test:/\.html$/,
                loader:'html-loader',
                options:{
                    esModule:false
                }
            },
            //打包其他文件
            {
                exclude:/\.(js|css|less|html|jpg|png|gif)$/,
                loader:'file-loader',
                options:{
                    outputPath:'media'
                }
            }
        ]
    },
    plugins:[
        //提取css文件
        new MiniCssExtractPlugin({
            filename:"css/built.css"
        }),
        //压缩css
        new OptimizeCssAssetsWebpackPlugin(),
        //打包html
        new HtmlWebpackPlugin({
            template:'./src/index.html',
            //压缩html
            minify:{
                collapseWhitespace:true,
                removeComments:true
            }
        })
    ],
    // 开启生产模式就自动压缩js
    mode:'production'
}

性能优化介绍

开发环境性能优化

  • 1优化打包速度
  • 2优化代码调试 生产环境性能优化
  • 1优化打包速度
  • 2优化代码性能

HMR

hot module replacement 热模块替换 作用当一个模块发生变化只会打包这一个模块而不是所有模块

devServer:{
    ....,
自动打开浏览器
  open:true,
  //开启hmr
  hot:true
}

样式文件 style-loader 可以hmr js文件默认没有hmr,在index.js文件下写(之后监听非入口js文件)

module.hot.accept('./print.js',function(){
//会监听print.js的变化,
}    

html文件:默认不能hmr 同时会导致问题:html不能热更新了 解决 修改entry入口

source-map(开发环境调试代码)

source-map 是一种提供源代码到映射代码的技术(如果后代们出错了,通过映射可以追溯到源代码)

devServer:{
    ....,
自动打开浏览器
  open:true,
  //开启hmr
  hot:true
}
devtool:'
/*
 
*/

uTools_1651044305988.png [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MEWfgBAF-1608720242913)(../webpack-imgs/1800757544-5c7a5004f417e_articlex.png)]'

uTools_1651043818576.png

uTools_1651043873641.png

uTools_1651044444910.png

oneOf

    rules:[
        oneOf:[
            {
                test:
                use:[]
           }
        ]
    ]

缓存

这里是在缓存打包后的js文件,尽量少替换,客户端也就少下载了
babel缓存

uTools_1651045562146.png 文件资源缓存
在文件名加哈希值 这样当文件资源改动时 浏览器也会刷新 而不是使用强制缓存的内容
问题 因为js和css同时使用一个哈希值 如果重新打包会导致所有缓存失效但是我只改了一个文件
解决:fileName:

 filename:"css/built.[contenthash:10].css"

uTools_1651046607690.png

tree shaking

目的 去除没有使用的代码,使体积更小 使用条件

  • 1 必须使用es6模块化
  • 2 mode开启production环境 在package.json设置

uTools_1651047221824.png

code spilt(代码分割)非常重要的

比如把一个文件分割成多个文件 多入口文件 第一种 uTools_1651053637244.png 第二种

  • 单入口 只会把node包的文件单独打包
  • 多入口 把node包的文件单独打包然后会把公共引入的文件单独打包(只因入一次的不会单独打包)

uTools_1651054162685.png 第三种

uTools_1651054830737.png

懒加载和预加载

懒加载 利用代码分割的思路 预加载

uTools_1651059391710.png

PWA:

渐进式网络开发应用程序(离线可访问)
安装 npm i work-webpack-plugin@5
引入 const WorkboxWebpackPlugin=require('worbox-webpack-plugin')\

uTools_1651060095456.png 注册 在入口文件inde。js下

uTools_1651060509883.png

多进程打包

下载 npm i thread-loader只有工作耗时较长才需要多进程打包
写在和loader同一个use数组上 如babel-loader 如果需要图片多线程就需要写在图片的loader的use数组(注意 loader的书写顺序)

uTools_1651061521457.png

externals

和plugin同级 uTools_1651061976232.png 然后再html文件中通过如cdn等使用script标签直接引入JQuery

dll

1 单独写一个xxxx.js 然后书写以下内容

uTools_1651062654554.png 命令 webpack --config xxx.js会把引用的库打包

2 webpackconfig。js下 书写

uTools_1651063068630.png 3 安装add-asset-html-webpack-plugin npm i add-asset-html-webpack-plugin 然后引入 然后注册 uTools_1651063348099.png

uTools_1651063530174.png

性能优化总结