webpack相关问题

写在前面,这是我个人对webpack中一些常见的问题做的总结。小白一枚,不具有深度参考价值、

webpack是什么?和Gulp相比有什么区别?

webpack可以看做是模块打包机,是一个前端资源打包工具,它将根据模块的依赖关系进行分析,然后按照指定的规则生成对应的静态资源。

为什么要使用webpack?

  • 前端模块化
  • css预处理器

与Gulp的区别

Gulp/Grunt是一种能够优化前端的开发流程的工具,而WebPack是一种模块化的解决方案,不过Webpack的优点使得Webpack在很多场景下可以替代Gulp/Grunt类的工具。

gulp可以进行js,html,css,img的压缩打包,是自动化构建工具,可以将多个js文件或是css压缩成一个文件,并且可以压缩为一行,以此来减少文件体积,加快请求速度和减少请求次数;并且gulp有task定义处理事务,从而构建整体流程,它是基于流的自动化构建工具。

webpack的工作方式是:把项目当成一个整体,通过一个给定的入口文件,webpack将从这个文件开始找到项目的依赖文件,用loader处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件

loader和plugin的使用和区别

loader

通过使用不同的loader,webpack有能力调用外部的脚本或工具,实现对不同格式的文件的处理,比如转换scss为css或者吧es6、es7转换成浏览器兼容的js文件。对于react而言,合适的Loaders可以把React的中用到的JSX文件转换为JS文件。
常见的loader有style-loader、css-loader、less-loader、babel-loader、url-loader等
Loaders需要单独安装并且需要在webpack.config.js中的modules关键字下进行配置,Loaders的配置包括以下几方面:

  • test:一个用以匹配loaders所处理文件的拓展名的正则表达式(必须)
  • loader:loader的名称(必须)
  • include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
  • query:为loaders提供额外的设置选项(可选)

在webpack.config.js中单独配置modules

 module:{
        // 配置所有第三方loader模块
        rules:[
            {test:/\.css$/,use:['style-loader','css-loader']},
            {test:/\.less$/,use:['style-loader','css-loader','less-loader']},
            // 当图片大小大于或者等于给定值得时候,则不会被转为base64格式。如果图片大小小于这个值,则会被转为base64格式
            // {test:/\.(jpg||png||jpeg||gif||bmp)$/,use:'url-loader?limit=52451&name=[hash:8]-[name].[ext]'}//处理图片路径的
            {test:/\.(jpg||png||jpeg||gif||bmp)$/,use:'url-loader?limit=52451'},
            {test:/\.(ttf||eot||svg||woff||woff2)$/,use:'url-loader'},//处理字体文件的loader
            {test:/\.js$/,use:'babel-loader',exclude:/node_modules/},
            {test:/\.vue$/,use:'vue-loader'},//处理vue文件的loader
        ]
    }

插件(Plugins)

插件是来拓展Webpack功能的,它会在整个构建过程中生效,执行相关的任务。
loader和plugins常常被弄混,但是他们完全不同,主要区别在于,loader是打包构建过程中用来处理源文件的(JSX、Scss、Less)一次处理一个,插件并不直接操作单个文件,它对整个构建过程起作用。
常用的插件有

html-webpack-plugin

在内存中,根据指定的模板页面生成一份内存中的首页,同时将打包好的bundle.js注入到页面底部

优化插件
  • OccurenceOrderPlugin::为组件分配ID,通过这个插件webpack可以分析和优先考虑使用最多的模块,并为它们分配最小的ID
  • UglifyJsPlugin:压缩JS代码;
  • ExtractTextPlugin:分离CSS和JS文件

需要在webpack.config.js中引入插件,然后再单独配置plugins

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
    plugins:[
        // 所有webpack插件的配置节点
        new htmlWebpackPlugin({
            template:path.join(__dirname,'./src/index.html'),
            filename:'index.html'//设置生成的页面名称
        }),
        new VueLoaderPlugin()
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.optimize.UglifyJsPlugin(),
        new ExtractTextPlugin("style.css")
    ]

npm中-S和-D的区别

  • npm install xxx -S,也就是 npm install module_name --save 写入dependencies
  • npm install xxx -D,也就是 npm install module_name --save-dev 写入devDependencies

devDependencies ,是我们开发的时候需要用到的一些包(大部分都是-D,各种loader,包括gulp、webpack以及webpack-dev-server),只需要用于开发阶段,真正打包上线的时候并不需要这些包,因为这些工具只是你用来打包代码的,是用来识别特定文件以及代码,帮助我们生产最终文件的
dependencies,这个则是需要发布到生产环境中的(vue全家桶,前端UI),就比如你要跑一个基于vue的项目,所以需要vue.js来支持,而这个vue.js文件就需要跟随项目到最终的生产环境

webpack打包原理

首先回顾几个核心的概念

  • entry :入口,webpack执行构建的第一步就是从入口开始(一般是src的main.js)
  • module: 模块,webpack中一切皆模块,一个模块对应一个文件,webpack从配置的entry开始递归寻找所有依赖的模块
  • Chunk:代码块,一个Chunk由多个模块组合而成,用于代码合并与分割
  • Loader:模块转换器,用于把模块原内容按照需求转换成新内容
  • Plugin:扩展插件,在Webpack构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件的发生,在特定时机做对应的事情

webpack只是一个打包模块的机制,只是把依赖的模块转化成可以代表这些包的静态文件。webpack就是识别你的 入口文件,识别你的模块依赖,来打包你的代码。
webpack做的就是分析代码。转换代码,编译代码,输出代码。

webpack中每个模块有一个唯一的id,是从0开始递增的。整个打包后的bundle.js是一个匿名函数自执行。参数则为一个数组。数组的每一项都为个function。function的内容则为每个模块的内容,并按照require的顺序排列。

打包流程

1、初始化:启动构建,读取与合并配置参数,加载plugin,实例化Compiler
2、编译:从entry出发,针对每个module单串行调用对应的loader,再找到module依赖的module,递归的进行编译处理
3、输出:对编译后的module组合成chunk,转换成文件,输出到文件系统。

webpack打包优化

体积大小优化

1、开启webpack4.x mode的生产模式

webpack4.x以后有一个mode选项,可以配置两种打包环境,一个是开发环境development一个是生产环境production
打包的时候使用webapck --mode=production命令打包,这个是代码压缩过的
或者在webpack.config.js中进行配置

mode:‘production’,//产品模式会被压缩,开发模式不会被压缩

2、提取公共依赖

抽离的公共依赖满足的条件:
(1)体积过大
(2)不经常更新
(3)依赖较多
常见的满足这类条件的包有:react,react-dom,redux,react-redux,jquery等
使用 CommonsChunkPlugin 插件,将多个 js 文件进行提取,建立一个独立的文件。这个文件包含一些共用模块,浏这样览器只在刚开始的时候加载一次,便缓存起来供后续使用。而不用每次访问一个新界面时,再去加载一个更大的文件。

entry:{
 app:'./entry',
 vendor:['react','other-lib'],
 },
 plugins:[
 new Webpack.optimize.CommonsChunkPlugin({
   name: 'vendor',
 }),
 ]
3、优化devtool中的source-map

dev-tool 提供了很多种选项,用来增强我们 debug 的能力,我们熟知的有: source-map , inline-source-map , cheap-source-map 等等。如果你的文件在打包之后突然变成好几M,那么不用想,肯定是因为 source-map 的原因。 source-map 在开发阶段确实很好用,调试起来很方便,但是在生产环境下就没必要部署了。 建议在 prod 环境下关闭 source-map

4、使用CDN引入

webpack 提供Externals的方法,可以通过外部引用的方法,引入第三方库
index.html中:

<script src="https://code.jquery.com/jquery-3.1.0.js"></script>

webpack.config.js中配置:

module.exports = {
   externals: {
     jquery: 'jQuery'
   }
};

5、使用 UglifyJSPlugin 压缩

通过 UglifyJSPlugin 可以压缩我们的 *.js 文件。 安装方法: npm install uglifyjs-webpack-plugin --save-dev 。

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
 plugins: [
   new UglifyJSPlugin({
      parallel: 4,
      uglifyOptions: {
        output: {
          comments: false,
          beautify: false,
        },
        compress: {
          warnings: false
        },
      },
      cache: true,
    }),
 ]
6、开启gzip压缩等

我们使用 compression-webpack-plugin 插件进行压缩。 安装: npm install compression-webpack-plugin --save-dev

const CompressionPlugin = require("compression-webpack-plugin");
plugins:[
new CompressionPlugin({
 asset: '[path].gz[query]', //目标资源名称。[file] 会被替换成原资源。[path] 会被替换成原资源路径,[query] 替换成原查询字符串
   algorithm: 'gzip',//算法
   test: new RegExp(
     '\\.(js|css)$'  //压缩 js 与 css
   ),
   threshold: 10240,//只处理比这个值大的资源。按字节计算
   minRatio: 0.8//只有压缩率比这个值小的资源才会被处理
})
]

速度优化

1.优化loader配置

缩小文件匹配范围(include/exclude)
通过排除node_modules下的文件 从而缩小了loader加载搜索范围 高概率命中文件

2、resolve优化配置

2.1 优化模块查找路径 resolve.modules

Webpack的resolve.modules配置模块库(即 node_modules)所在的位置,在 js 里出现 import ‘vue’ 这样不是相对、也不是绝对路径的写法时,会去 node_modules 目录下找。但是默认的配置,会采用向上递归搜索的方式去寻找,但通常项目目录里只有一个 node_modules,且是在项目根目录,为了减少搜索范围,可以直接写明 node_modules 的全路径;同样,对于别名(alias)的配置,亦当如此:

const path = require('path');
function resolve(dir) { // 转换为绝对路径
  return path.join(dirname, dir);
}
resolve: {
 modules: [ // 优化模块查找路径
    path.resolve('src'),
   path.resolve('node_modules') // 指定node_modules所在位置 当你import 第三方模块时 直接从这个路径下搜索寻找
  ]
}

2.2 resolve.alias 配置路径别名
创建 import 或 require 的路径别名,来确保模块引入变得更简单。配置项通过别名来把原导入路径映射成一个新的导入路径 此优化方法会影响使用Tree-Shaking去除无效代码。
例如,一些位于 src/ 文件夹下的常用模块


alias: {
 Utilities: path.resolve(dirname, 'src/utilities/'),
 Templates: path.resolve(dirname, 'src/templates/')
}

2.3resolve.extensions

当引入模块时不带文件后缀 webpack会根据此配置自动解析确定的文件后缀
后缀列表尽可能小
频率最高的往前放
导出语句尽可能带上后缀

resolve: {
  extensions: ['.js', '.vue']
}

现在,替换「在导入时使用相对路径」这种方式,就像这样:

import Utility from '../../utilities/utility';

你可以这样使用别名:

import Utility from 'Utilities/utility';
3、ParallelUglifyPlugin

这个插件可以帮助有很多入口点的项目加快构建速度。把对JS文件的串行压缩变为开启多个子进程并行进行uglify。

cnpm i webpack-parallel-uglify-plugin -D

参考资料

https://www.jianshu.com/p/42e11515c10f
https://www.jianshu.com/p/e24ed38d89fd
https://www.jb51.net/article/135991.html
https://segmentfault.com/a/1190000011138081?utm_source=tag-newest
webpack原理(真的超级全面了,收藏留着以后慢慢看)
https://blog.csdn.net/weixin_40811829/article/details/88599201

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值