webpack官网:https://webpack.js.org/
webpack中文文档: https://www.webpackjs.com/concepts/
1.什么是webpack
概念:本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
简单理解:webpack是一个打包模块化javascript的工具,在webpack里一切文件皆模块,通过loader转换文件,通过plugin注入钩子,最后输出由多个模块组合成的文件,webpack专注构建模块化项目。
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。
2.基本使用
webpack基本使用
配置完访问localhost:8080可以直接访问页面(不配置的话访问看到的页面是项目目录,然后再点击进去访问)
配置完运行npm run dev打包之后可以直接打开页面,不用再复制访问地址。
webapck的加载器loader
没有loader加载器打包css文件报错:
基本使用:
webpack默认不打包样式表中的图片,如css文件中的背景图片的url。所以需要借助url-loader来进行打包,否则会报错。
几个常见的loader
file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去
source-map-loader:加载额外的 Source Map 文件,以方便断点调试
image-loader:加载并且压缩图片文件
babel-loader:把 ES6 转换成 ES5
css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。
eslint-loader:通过 ESLint 检查 JavaScript 代码
webpack中的plugin
什么是plugin
plugin是一个具有 apply方法的 js对象。 apply方法会被 webpack的 compiler(编译器)对象调用,并且 compiler 对象可在整个 compilation(编译)生命周期内访问。
一个plugin看起来大概是这个样子:
function CustomPlugin(options){
// options是配置文件,你可以在这里进行一些与options相关的工作
}
// 每个plugin都必须定义一个apply方法,webpack会自动调用这个方法
CustomPlugin.prototype.apply = function(compiler){
......
});
}
module.exports = CustomPlugin;
plugin有什么用
plugin是webpack核心功能,通过plugin(插件)webpack可以实现loader所不能完成的复杂功能,使用plugin丰富的自定义API,可以控制webpack编译流程的每个环节,实现对webpack的自定义功能扩展。
举例 我们实际项目中就使用了HtmlWebpackPlugin插件,它帮助我们做了下面几件事儿:
在工程打包成功后会自动生成一个html模板文件
同时所依赖的CSS/JS也都会被自动引入到这个html模板文件中
设置生成hash添加在引入文件地址的末尾,类似于我们常用的时间戳,来解决可能会遇到的缓存问题。
使用plugin
在 webpack 配置文件(webpack.config.js)中,向 plugins 属性传入 new 实例即可。比如:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = {
module: {
loaders: [
{
test: /\.(js|jsx)$/,
loader: 'babel-loader'
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin(), //访问内置的插件
new HtmlWebpackPlugin({template: './src/index.html'}) //访问第三方插件
]
};
注意
webpack中的插件分为内置插件和第三方插件
内置插件不需要额外安装依赖,如上面的例子中:UglifyJsPlugin插件
如果是第三方插件,如上面的例子中HtmlWebpackPlugin插件,则使用之前需要进行安装:
npm install html-webpack-plugin --save-dev
几个常见的plugin
BannerPlugin:对所有的文件打包后添加一个版权声明
uglifyjs-webpack-plugin: 对JS进行压缩混淆
HtmlWebpackPlugin:可以根据模板自动生成html代码,并自动引用css和js文件
Hot Module Replacement:在每次修改代码保存后,浏览器会自动刷新,实时预览修改后的效果
copy-webpack-plugin:通过Webpack来拷贝文件
extract-text-webpack-plugin:将js文件和css文件分别单独打包,不混在一个文件中
DefinePlugin 编译时配置全局变量,这对开发模式和发布模式的构建允许不同的变量时非常有用
optimize-css-assets-webpack-plugin 不同组件中重复的css可以快速去重
更多可点击这里查看。
3.vue-loader
4.vue中配置webpack
5. 关闭eslint
在vue.config.js文件中添加一项lintOnSave: false
和在devServer项中设置overlay
中的错误提示为false。
module.exports = {
devServer: {
port: 8081,
open: true,
overlay: {
warnings: false,
errors: false
}
},
lintOnSave: false
}
6.webpack优缺点
webpack有哪些优点
专注于处理模块化的项目,能做到开箱即用,一步到位
可通过plugin扩展,完整好用又不失灵活
使用场景不局限于web开发
社区庞大活跃,经常引入紧跟时代发展的新特性,能为大多数场景找到已有的开源扩展
良好的开发体验
webpack的缺点
- webpack的缺点是只能用于采用模块化开发的项目
7.分别介绍bundle,chunk,module是什么
bundle:是由webpack打包出来的文件。 chunk:代码块,一个chunk由多个模块组合而成,用于代码的合并和分割。 module:是开发中的单个模块,在webpack的世界,一切皆模块,一个模块对应一个文件,webpack会从配置的entry中递归开始找出所有依赖的模块。
8.分别介绍什么是loader?什么是plugin
loader:模块转换器,用于将模块的原内容按照需要转成你想要的内容。 plugin:在webpack构建流程中的特定时机注入扩展逻辑,来改变构建结果,是用来自定义webpack打包过程的方式,一个插件是含有apply方法的一个对象,通过这个方法可以参与到整个webpack打包的各个流程(生命周期)。
9.什么是模块热更新
模块热更新是webpack的一个功能,他可以使得代码修改过后不用刷新浏览器就可以更新,是高级版的自动刷新浏览器。 devServer中通过hot属性可以空时模块的热替换
1,通过配置文件
const webpack = require('webpack');
const path = require('path');
let env = process.env.NODE_ENV == "development" ? "development" : "production";
const config = {
mode: env,
devServer: {
hot:true
}
}
plugins: [
new webpack.HotModuleReplacementPlugin(), //热加载插件
],
module.exports = config;
2,通过命令行
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "NODE_ENV=development webpack-dev-server --config webpack.develop.config.js --hot",
}
10.什么是Tree-shaking
Tree-shaking可以用来剔除javascript中不用的死代码,它依赖静态的es6模块化语法,例如通过哦import 和export 导入导出,Tree-shaking最先在rollup中出现,webpack在2.0中将其引入,css中使用Tree-shaking需要引入Purify-CSS。
11.通过webpack处理长缓存
浏览器在用户访问页面的时候,为了加快加载速度,会对用户访问的静态资源进行存储,但是每一次代码升级或是更新,都需要浏览器去下载新的代码,最方便和简单的更新方式就是引入新的文件名称。在webpack中可以在output纵输出的文件指定chunkhash,并且分离经常更新的代码和框架代码。通过NameModulesPlugin或是HashedModuleIdsPlugin使再次打包文件名不变。
12.如何提高webpack的构建速度
1. 通过externals配置来提取常用库
2. 利用DllPlugin和DllReferencePlugin预编译资源模块
通过DllPlugin来对那些我们引用但是绝对不会修改的npm包来进行预编译,再通过DllReferencePlugin将预编译的模块加载进来。
3. 使用Happypack 实现多线程加速编译
要注意的第一点是,它对file-loader和url-loader支持不好,所以这两个loader就不需要换成happypack了,其他loader可以类似地换一下
4. 使用Tree-shaking和Scope Hoisting来剔除多余代码
5. 使用fast-sass-loader代替sass-loader
6. babel-loader开启缓存
babel-loader在执行的时候,可能会产生一些运行期间重复的公共文件,造成代码体积大冗余,同时也会减慢编译效率。 可以加上cacheDirectory参数或使用 transform-runtime 插件试试。
// webpack.config.js
use: [{
loader: 'babel-loader',
options: {
cacheDirectory: true
}]
// .bablerc
{
"presets": [
"env",
"react"
],
"plugins": ["transform-runtime"]
}
7. 不需要打包编译的插件库换成全局"script"标签引入的方式
比如jQuery插件,react, react-dom等,代码量是很多的,打包起来可能会很耗时 可以直接用标签引入,然后在webpack配置里使用 expose-loader 或 externals 或 ProvidePlugin 提供给模块内部使用相应的变量。
// @1
use: [{
loader: 'expose-loader',
options: '/pre>
}, {
loader: 'expose-loader',
options: 'jQuery'
}]
// @2
externals: {
jquery: 'jQuery'
},
// @3
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
8. 优化构建时的搜索路径
在webpack打包时,会有各种各样的路径要去查询搜索,我们可以加上一些配置,让它搜索地更快 比如说,方便改成绝对路径的模块路径就改一下,以纯模块名来引入的可以加上一些目录路径 还可以善于用下resolve alias别名 这个字段来配置。 还有exclude等的配置,避免多余查找的文件,比如使用babel别忘了剔除不需要遍历的。
参考链接
webpack面试题汇总
Webpack打包构建太慢了?试试几个方法
关于webpack的面试题总结