IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> webpack -> 正文阅读

[JavaScript知识库]webpack

webpack核心概念

entry(入口)

string

//单入口,此时形成一个chunk,对应一个bundle文件。默认名是main
entry:'./src/index.js'

array

在HMR的热更新中让html生效用的最广。

//多入口,只会形成一个chunk,对应一个bundle文件。默认名main
entry:['./src/index.js','./src/test.js']

object

//多入口,有几个入口文件,就会生成对应chunk。名字是以键值对呈现的 key
entry:{
    index:'./src/index.js'
    test:'./src/test.js'
}

对象的特殊用法

entry:{
    //会生成一个chunk,输出只有一个bundle。名字是index
    index:['./src/index.js','./src/add.js']
    //生成一个chunk,输出只有一个bundle
    test:'./src/test.js'
}

outPut(输出)

const {reslove} = require('path')
entry:'./src/index.js'
output:{
    //输出的文件名称(可以加路径)
    filename:'js/[name].js',
    //输出的路径,绝对路径。 将来所有资源输出的公共路径
    path:reslove(__dirname,'build'),
    //所有资源引入公共前缀 -->imgs/a.jpg   /imgs/a.jpg  .第一个会在当前目录下查找,而第二个会在总文件下查找
    publicPath:'/',
    //所有非入口chunk的文件名。 也就是除了入口chunk的文件名,这里设置其他chunk的名字.
        //比如通过import引入的,和optimization创建的chunk
    chunkFilename:'js/[name]_chunk.js',
    //library通常结合dll使用,将哪些库暴露出去
    library:'[name]' //暴露变量名
    //变量名添加到哪个browser上 有commomjs ,global ,window
    libraryTarget:'window'
}

modules(模块)

module:{
    rules:[
        {
            test:/\.css$/,
            //多个loader用use,单个loader用loader
            use:['style-loader','css-loader']
        },{
            test:/\.js$/,
            //排除node_modules的js文件
            exclude:'node_modules',
            //只检查src下面的js文件
            include:resolve(__dirname,'src'),
            //优先执行,延迟执行 post
            enforce:'pre',
            loader:'eslint-loader',
            //loader配置选项
            options:{}
        },{
            //一下配置生成一个,优化打包速度
            oneOf:[]
        }
    ]
}

resolve

//解析模块的规则,后面写项目,可以简写路径
resolve:{
    //配置解析别名
    alias:{
        css:resolve(__dirname,'src/css').
        //可以写多个
    },
    //配置省略文件的后缀名,引入的时候就不用写后缀名了
    extensions:['js','json','css'],
    //告诉webpack解析目录是去哪个目录,默认node_modules
    modules:['node_modules']
}

devServer

//devServer构建本地服务器,用于开发环境
devServer:{
     //运行代码的目录,和输出路径应该一致
    contentBase:reslove(__dirname,'build'),
    //监视contentBase目录下的所有文件,一旦文件变化就reload
    watchcontentBase:true,
    watchOptions:{
        //忽略文件
        ignored:/node_modules/
    },
    //启动gzip压缩
    compress:true,
    //端口号,默认8080
    port:'8080',
    //域名
    host:'localhost',
    //自动打开浏览器
    open:true,
    //开启HMR功能
    hot:true,
    //不要显示启动服务器而出现日志信息
    clientLogLevel:'none',
    //除了一些基本启动信息,其他内容都不要显示
    quiet:true,
    //如果出错,不要全屏显示
    overlay:false,
    //服务器代理----解决开发环境跨域问题
        //问题出现:浏览器和服务器是有跨域问题的,服务器之间是没有跨域问题的,
        //处理方案:通过服务器之间的请求转化,从而解决跨域问题
     proxy:{
         //一旦devServer(8080)接受到 /api/xxx 的请求,就会把请求发送到另外一个服务器上(8000)
         '/api':{
             target:'http://loaclhost:8000',
              //发送路径时,将请求路径重写 将 /api/xxx --> /xxx (去掉/api)
              pathRewrite:{
                  '^/api':''
              }
         }
     }
}

optimization

optimizition:{
    //提取公共代码成单独chunk进行打包
    splitChunks:{
        chunk:'all',
        miniSize:30 * 1024  //分割的chunk最小为30kb
        maxSize:0        //最大没有限制
        minChunks:1      //提取的chunk最少被引用1次
        maxAsyncRequests:5  //按需加载时并行加载的文件的最大数量
        maxInitialRequests:3  //入口js文件最大并行请求数量
        automaticNameDelimiter:'~'  //名称连接符
        name:true    //可以使用命名规则
        cacheGroups:{
            //分割chunk组
            //...太多了,不写了
        }
        
    },
     //会记录其他文件发生变化的哈市,单独打包成一个runtime文件
    //修改在index.js中修改a文件导致b文件的contenthash发生变化
    runtimeChunk:{
        name:entrypoint => runtime-${entrypoint.name}
    },
    minimizer:{
        //配置生产环境的压缩方案:js和css。改为生产模式也可以,但是不再维护了
        new TerserWebpackPlugin({
            //开启缓存
            cache:true,
            //开启多进程打包
            parallel:true,
            //启动source-map
            sourceMap:true
        })
    }
}

webpack运行

首先要在终端里面初始化nodejs相关文件,即 npm i

然后下载webpack npm i webpack webpack-cli D D就是开发时依赖

  1. 引入css,less等样式文件。需要安装对应loader、

  2. 引入html文件,需要下载 html-webpack-plugin 插件,然后在plugins里面new HtmlWebpackPlugin()

  3. 引入图片资源 需要下载url-loader和file-loader

js相关处理

js兼容性处理

因为平常写代码难免会写到es6中代码,而低版本浏览器又不认识es6代码,所以我们要进行js兼容性处理

都是在webpack.config.js中module块中rules里面配置的

  // js兼容性处理:babel-loader   @babel/core是基础,这两个都要下
  //1.基本兼容性处理  @babel/preset-env
 // 问题:只能检测基础语法,像promise这中高级语法不能检测
// 2.全部js兼容性处理 @babel/polyfill 直接下载,然后再index.js中import直接引用就行
// 问题:我们只需要解决部分兼容性问题,而他是将所有兼容性代码全部引入,文件就太大了
// 3. 需要做兼容性处理:按需加载-- core-js  还是要先下载
 {
     test:/\.js$/,
     exclude:/node_modules/,
     loader:'babel-loader',
     options:{
         //预设,指示babel做怎样的兼容性处理
         presets:{
             [
                 '@babel/preset-env',
                 {
                     //按需加载
                     useBuiltIns:'usage',
                     //指定core-js版本
                     corejs:{
                         version:3
                     },
                     //指定兼容做到哪个浏览器,具体环境具体定
                     targets:{
                         chrome:'60',
                         firefox:'60',
                         ie:'9'
                     }
                 }
             ]
         }
     }
 }

最后我们是用第一种方法和第三种方法合并这处理js兼容问题

js压缩

js压缩我们只需要将开发模式转化为生产模式,会自动压缩

mode:'production'

js语法检测

{
    test:/\.js$/,
    exclude:/node_modules/,
    loader:'eslint-loader',
    options:{
        //自动修复eslint报错
        fix:true
    }
}

他本身是没有规则的,所以我们要继承airbnb第三方库的规则。在package.json中配置如下

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

当js文件同时被处理

当js文件同时被多个loader处理,一定要规定先后顺序

比如上面的被eslint-loader处理同时被babel-loader处理

先处理eslint-loader,再处理babel-loader

    test:/\.js$/,
    exclude:/node_modules/,
    //优先执行
    enforce:'pre',
    loader:'eslint-loader',

只需要加入 enforce:‘pre’ 即可

css相关处理

1.css样式单独提取

new MiniCssExtractPlugin = require('mini-css-extract-plugin')
module:{
    rules:[
        {
            test:/\.css$/,
            use:[
               // 'style-loader',
                MiniCssExtractPlugin.loader,
                'css-loader'
            ]
        },{
            test:/\.less$/,
            use:[
              //  'style-loader',
                MiniCssExtractPlugin.loader,
                'css-loader',
                'less-loader'
            ]
        }
    ]
},
plugins:[
    new  MiniCssExtractPlugin({
        //给文件重命名
        filename:'css/buit.css'
    })
]

2.兼容性处理

兼容性处理要用postcss-loader

new MiniCssExtractPlugin = require('mini-css-extract-plugin')
//配置nodejs环境变量,可以决定browserslist使用哪个环境变量
process.env.NODE_ENV = 'production'
//考虑代码的复用性,可以单独提取出来
const CssLoader = [
   MiniCssExtractPlugin.loader,
   'css-loader',
     //下面这些,还要再package.json中定义browserslist
    {
   loader:'postcss-loader',
   options:{
   ident:'postcss',
     plugins:()=>[
    require('postcss-preset-env')()
     ]
  }
 }
]
module:{
    rules:[
        {
            test:/\.css$/,
            use:[...CssLoader]
        },{
            test:/\.less$/,
            use:[..CssLoader,'less-loader']
        }
    ]
},
plugins:[
    new  MiniCssExtractPlugin({
        //给文件重命名
        filename:'css/buit.css'
    })
]

再package.json中配置browserslist

  "browserslist":{
    "development":[
          "last 1 chrome version",
          "last 1 firefox version",
          "last 1 safari version"
    ],
    "production":[
          ">0.2%",
          "not dead",
          "not op_mini all"
    ]
  }

css压缩

const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
plugins:[
    new   OptimizeCssAssetsWebpackPlugin()
]

其他相关处理

图片压缩处理

{
    test:/\.(jpg|png|svg|gif)$/,
    loader:'url-loader',
    options:{
        limit: 8*1024,
        name:'[hash:10].[ext]',
        //输出的路径不要直接放在bundle.js下面,应该划分开
        outputPath:'imgs',
        esModule:false
    }
}

HTML压缩处理

new HtmlWebpackPlugin = require('html-webpack-plugin')
plugins:[
    new  HtmlWebpackPlugin({
        //以指定html为模板创建新的html文件。直接new调用不传参,是创建空的html文件
        template:'./src/index.html',
        minify:{
            //去除空格
            collapseWhitespace:true,
            //去除注释
            removeComments:true
        }
    })
]

处理html压缩之后,我们会发现html中的图片并不能压缩处理

HTML中图片资源处理

{
    test:/\.html$/,
    loader:'html-loader'
}

**这里设置好之后,用的是commonjs,与图片压缩所使es6冲突,所以要在图片压缩加入 esModule:false **

其他资源处理

{
    //其他资源处理,会原封不动的输出出去
    exclude:/\.(js|css|html|less|png|)/,
    loader:'file-loader',
    options:{
        outputPath:'media'
    }
}

环境优化

为什么要优化?

如果我们的源文件中有大量的css,js代码。我们修改其中的一个,则会重新进行打包,会将所有的源文件重新打包。我们是不希望这样的。

1.HMR基于开发环境

HMR: hot module replacement 热模块替换/模块热替换 是基于开发环境的

作用:一个模块发生变化,只会宠幸打包这一个文件,而不是打包所有的源文件

样式文件:可以使用HMR,因为在style-loader内部实现了,所以在开发环境中,都用style-loader

js文件:默认不能使用HMR.要使用,在对应js文件中添加如下代码。。。不能处理入口文件!!!!

if(module.hot){
    //这里以build.js为例子,不能处理入口js文件
    moule.hot.accept('./build.js',function(){
        //会监听index.js的变化,一旦发生变化,就会执行这里的函数
    })
}

HTML文件:默认不能使用。 解决:修改entry入口,将html资源引入即可

//再搭建本地服务器内
devServer:{ 
    contentBase:reslove(__dirname,'bundle'),
    inline:true,
    //开始HMR功能
    hot:true
}

2.source-map

source-map 是提供源代码到构建后代码映射技术

如果构建后代码出错了,可以通过映射的方法找到对应源代码。

只要在webpack.config.js中加入

devtool:'source-map'
  1. source-map 外部
  2. inline-source-map 在js内部生成source-map 内联
  3. hidden-source-map 外部
  4. eval-source-map 每一个文件都生成对应的source-map,在eval函数里面。都在js中 内联
  5. nosources-source-map 外部
  6. cheap-source-map 外部会成成.map文件
  7. cheap-module-source-map 外部 6和7的区别 module:会将loader的source-map加入

外部与内联的区别:

  1. 外部生成了.map文件,内联没有
  2. 内联构建速度更快
  3. 内联会使代码体积变大

开发环境与生产环境

1.开发环境:速度快,调试方便

  1. 速度快(eval>inline>cheap)

    1. eval-cheap-source-map
    2. eval-source-map
  2. 调试更友好

    1. source-map
    2. cheap-moudle-source-map
    3. cheap-source-map

综上,—》 eval-source-map

2.生产环境:源代码要不要隐藏,调试要不要方便

内联会使代码体积变大,所以我们在选择的时候首先排除内联

如果需要隐藏 —》 nosources-source-map 全部隐藏 / hidden-source-map 之隐藏源代码,会提示构建后代码错误

不考虑隐藏 —》 source-map / cheap-module-source-map

oneof

oneof是提供优化生产环境打包配置的

比如:同时同时处理css文件和less文件,都需要css-loader,会让css-loader重复的执行,而oneof则会优化

module:{
    rules:[
        {
            //只需要将配置文件放入oneof中即可
            oneof:[]
        }
    ]
}

注意:两个loader处理一个时,则需要放在外面

比如:js文件需要eslint-loader处理和babel-loader处理。这个时候我们就需要单独提取出。

module:{
    rules:[
        {
          //这里放单独提取出的loader处理,只需要放一个  
        },
        {
            //只需要将配置文件放入oneof中即可
            oneof:[]
        }
    ]
}

缓存基于生产环境

当我们的js代码有很多时,我们修改其中的一个,并不希望所有的js代码都重新被打包。此时我们就要用到生产环境的缓存处理

babel缓存

让第二次打包构建速度更快

 {
     test:/\.js$/,
     exclude:/node_modules/,
     loader:'babel-loader',
     options:{
         //预设,指示babel做怎样的兼容性处理
         presets:{
             [
                 '@babel/preset-env',
                 {
                     //按需加载
                     useBuiltIns:'usage',
                     //指定core-js版本
                     corejs:{
                         version:3
                     },
                     //指定兼容做到哪个浏览器,具体环境具体定
                     targets:{
                         chrome:'60',
                         firefox:'60',
                         ie:'9'
                     }
                 }
             ],
                 //开启babel缓存,第二次构建的时候就会读取缓存
              cacheDirectory:true
         }
     }
 }

此时,用户第一次打开就会生成缓存,后面打开的话就会很快。

但是,如果你的js css代码修改的话,重新打包,页面将不会有任何反应,因为他们用的都是第一次留下的缓存

那我们怎么让他正常的处理呢? 我们对文件名加入hash值即可

文件资源缓存

让代码上线运行缓存更好使用

//在webpack.config.js中,所有的filename中加入hash值即可,比如下述代码
filename:'index[hash:10].js'

造成的问题:因为css和js同时使用一个hash值。

如果重新打包,会导致所有的缓存失效。(我们只想改变其中的一个文件)

chunkhash也不行,因为所引入的js。css等文件都是源自一个chunk,所以他们生成的哈希值也一样

contenthash不同文件会生成不同的哈希值,可以

filename:'index[contenthash:10].js'

tree shaking

作用:去除无用代码,让代码体积变小

前提:1.必须使用模块化 2.开启production环境

mode:'production'

在package.json中配置

"sideEffects":false  //所有代码都没有副作用,即可以进行tree shaking
问题:可能会把css / @babel/polyfill (副作用)等文件干掉 ,此时我们要再加
"sideEffects":["*.css"]  //这样即可

code split

code split就是解决防止打包后一个文件过大,而请求缓慢.

code split就是生成多个chunk,即把代码分成很多块

作用:1.可以将node_modules中代码单独打包一个chunk

? 2.自动分析多入口chunk中,有没有公共的文件,如果有则会打包成一个chunk

entry:'./src/index.js'  //单入口
entry:{  //多入口有几个文件就会输出几个文件,不同配置下面代码也可以
    index:'./src/index.js',
    test:'./src/test.js'
}

在后面加入下述代码即可

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

如果是单入口,则会将node_modules中代码单独打包一个chunk

如果是多入口,则自动分析多入口chunk中,有没有公共的文件,如果有则会打包成一个chunk

其次,我们还可以通过写js代码方式进行单独打包,首先要配置optimization和单入口

//这是在index.js中引入。假设有test.js和index.js在同一层级
import(/*webpackChunkname:'test'*/'./test')  //在/**/中可以指定生成对应名字
.then(()={
    //文件调用成功
}).catch(()=>{
    //文件加载失败
})

总结三种方法

  1. 使用多入口文件进行单独打包
  2. 引入optimization相关配置,会根据单入口,多入口进行打包
  3. 引入optimization相关配置,在js中写入对应js代码,进行单独打包

lazy loading

不是图片的懒加载,这里指的是js代码的懒加载

懒加载:当文件使用的时候加载

预加载 prefetch :等其他资源加载完,再加载…。 兼容性较差.一般都是用懒加载就够了

//这里比如当点击btn时,加载test.js文件
document.getElementById('btn').onclick = function(){
    import(/*webpackChunkName:'test',webpackPrefetch:true*/'./test.js').then(res=>{
        console.log(res)
    })
}

PWA

pwa即离线可访问技术。

const WorkboxWebpackPlugin = require('workbox-webpack-plugin')
//再通过plugins  中new调用
plugins:[
    new WorkboxWebpackPlugin.GenerateSW({
        //会生成serviceworker配置文件
        //1.帮助serviceworker快速启动
        //2.删除旧的servicewoker
        clientsClaim:true,
        skipWaiting:true
    })
]

然后还要去index.js中输入相应js代码

if('serviceWorker' in navigator){
    window.addEventListener('load',()={
        navigator.serviceWorker
        .register('/service-worker.js')
        .then(()=>{
           console.log('注册成功')
        .catch(()=>{
           console.log('注册失败')
           })
    })
    })
}

到这里,再打包eslint则会报错,不认识navigator等关键字,故我们要修改eslint中的配置

//在package.json中eslintConfig中添加下面代码
"env":{
    "browser":true    //支持浏览器全局变量
}

serviceWorker必须运行在服务器上

多进程打包

多进程打包主要用来优化打包速度。用的是thread-loader

在哪里用,在那里加就可以。基本是给js文件处理.

例如:

use:[
    {
        loader:'thread-loader',
        options:{
            workers:2  //z
        }
    }
    {
        loader:'babel-loader',
        options:{
            //...
        }
    }
]

开启多线程打包。只有工作消耗时间比较长,我们才开启多线程打包

否则会适得其反,多线程启动大概600ms

externals

可以禁止打包一些从cdn中可以获取到库,从而达到代码量少,在webpack.config.js中配置

externals:{
    //比如,拒绝vue被打包进来
    vue:'Vue'
}

然后在html中通过script标签引入cdn链接。

<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.0-beta.7/vue.cjs.js"></script>

dll

dll和上面的externals相似。dll是需要打包一次。而externals是不打包

我们要新建webpack.dll.js文件

const {resolve} = require('path')
const webpack = require('webpack')
module.exports = {
    entry:{
        //例如打包jquery. [name]--> jquery   ['jquery']-->代表要打包的库是jquery
        jquery:['jquery']
    },
    output:{
        filename:'[name].js',
        path:resolve(__dirname,'dll'),
        //打包的库向外暴露出去的名字
        library:'[name]_[hash]'
    },
    plugins:[
        //打包生成一个manifest.json 和jquery提供映射
        new webpack.DllPlugin({
            name:'[name]_[hash]' //暴露出去的名称
            path:resolve(__dirname,'dll/mainfest.json')//输出文件路径
        })
    ],
     mode:'production'
}

然后在config.js配置如下即可

const {resolve} = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
//webpack默认打包是config.js文件。可以通过引入然后调用改变默认打包文件
const webpack = require('webpack')
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
module.exprots = {
    entry:'./src/index.js',
    output:{
        filename:'built.js',
        path:resolve(__dirname,'build')
    },
    plugins:[
        new HtmlWebpackPlugin({
            filename:'./src/index.html'
        }),
        //告诉webpack哪些库不需要打包,也就是通过json文件映射到相应库,告诉webpack不参与打包
        new webpack.DllReferencePlugin({
            mainfest:resolve(__dirname,'dll/manifest.json')
        }),
        //将文件打包输出出去,并在html中自动引入资源
        new AddAssetHtmlWebpackPlugin({
            filepath:resolve(__dirname,'dll/jquery.js')
        })
    ],
    mode:'production'
}
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-11 18:43:10  更:2021-09-11 18:44:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:45:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码