Webpack学习
Webpack学习笔记
前端模块化
在了解Webpack
之前,必须说一下前端模块化的概念。
随着前端开发规模,以及代码逻辑复杂性的提高,在大型项目的开发中,大量forPage的js文件引用不仅显得很蠢且冗余,也给后期代码维护带来的很大的成本。所以引入了模块化开发的概念。
模块化开发,一个模块就是一个实现特定(且相对独立)功能的文件,有了模块我们就可以更方便的使用别人的代码,要用什么功能就加载什么模块。
模块化开发的四点好处
- 避免变量污染与命名冲突
- 提高代码(模块)的复用率
- 提高可维护性
- 依赖关系的统一管理
Webpack
的使用场景
目前,前端通用的模块化开发方式,以及目前我们项目组使用的Vue框架,以及Scss,less等CSS预处理器,这些改进确实大大的提高了我们的开发效率,但是利用它们开发的文件往往需要进行额外的处理才能让浏览器识别,而手动处理又是非常繁琐的,这就为Webpack
类的工具的出现提供了需求。
现在可以回答这个问题了,什么是Webpack
?
用我自己的理解方式来说,Webpack
就是项目各模块的打包工具。它通过分析项目结构,寻找各模块之间的依赖关系,将那些浏览器无法直接识别的文件(如.vue
),转换并统一打包成浏览器可识别的文件(如.js
)
Webpack的工作方式?
把项目当做一个整体,通过一个给定的主文件/入口文件(如:main.js
),Webpack
将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript
文件。
Webpack
的安装
//全局安装webpack npm i -g webpack //安装到项目目录 npm i --save-dev webpack
Webpack的配置项
1. 生成Source Maps
(方便调试)
通过打包完成的js文件,在调试的时候简直是灾难,难以找出出错位置与对应的代码位置,而Source Maps
就可以为我们解决这个问题。它提供了一种对应打包文件和源文件的方法,来方便我们进行调试。
在Webpack
的配置文件中配置Source Maps
,需要配置devtool
,共有四种配置选项:
devtool 配置选项 | 说明 |
---|---|
source-map | 在一个单独的文件中产生一个完整且功能完全的文件。这个文件具有最好的source map ,但是它会减慢打包速度 |
cheap-module-source-map | 在一个单独的文件中生成一个不带列映射的map,不带列映射提高了打包速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便 |
eval-source-map | 使用eval打包源文件模块,在同一个文件中生成干净的完整的source map 。这个选项可以在不影响构建速度的前提下生成完整的sourcemap ,但是对打包后输出的JS文件的执行具有性能和安全的隐患。在开发阶段这是一个非常好的选项,在生产阶段则一定不要启用这个选项 |
cheap-module-eval-source-map | 这是在打包文件时最快的生成source map的方法,生成的Source Map 会和打包后的JavaScript文件同行显示,没有列映射,和eval-source-map选项具有相似的缺点 |
上述选项从上到下打包速度越来越快,对打包后文件的执行影响也越来越大,因此在中小型项目中,eval-source-map
是一个很好的选项,注意只有在dev环境下使用它们,在prod环境下需要关闭该选项。
2. 实现热更新
Webpack
提供一个可选的本地开发服务器webpack-dev-server
,这个本地服务器基于node.js
构建
webpack-dev-server 配置选项 | 说明 |
---|---|
contentBase | 默认webpack-dev-server会为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录 |
port | 设置默认监听端口,如果省略,默认为”8080“ |
inline | 设置为true,当源文件改变时会自动刷新页面 |
historyApiFallback | 在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html |
3. Loaders
Webpack
相当重要的功能,通过使用不同的loader
,Webpack
可以使用外部工具来处理不同格式的文件,比如scss
转css
,(ES6,ES7的JS文件)转为现代浏览器兼容的JS文件Loaders
需要单独安装并且需要在webpack.xxx.config.js
中的modules
关键字下进行配置
Loaders 配置选项 | 说明 |
---|---|
test | 一个用以匹配Loaders 所处理文件的拓展名的正则表达式(必须) |
loader | loader 的名称(必须) |
include/exclude | 手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选); |
query | 为Loaders 提供额外的设置选项(可选) |
介绍之Babel
Babel
其实是一个编译JavaScript
的平台,它可以编译代码帮你达到以下目的:
- 让你能使用最新的
JavaScript
代码(ES6,ES7...),而不用管新标准是否被当前使用的浏览器完全支持; - 让你能使用基于
JavaScript
进行了拓展的语言,比如React
的JSX
由于Babel
的配置选项非常多,经常会把babel的配置选项放在.babelrc
的配置文件中
介绍之css-loader
和 style-loader
二者处理的任务不同,css-loader
使你能够使用类似@import
和 url(...)
的方法实现 require()
的功能,style-loader
将所有的计算后的样式加入页面中,二者组合在一起使你能够把样式表嵌入Webpack
打包后的JS文件中
- 关于
CSS modules
把JS的模块化思想带入CSS中来,通过CSS模块,所有的类名,动画名默认都只作用于当前模块。Webpack
对CSS模块化提供了非常好的支持,只需要在CSS loader
中进行简单配置即可,然后就可以直接把CSS的类名传递到组件的代码中,这样做有效避免了全局污染。具体代码如下
module.exports = { ... module: { rules: [ { test: /(\.jsx|\.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ }, { test: /\.css$/, use: [ { loader: "style-loader" }, { loader: "css-loader", options: { modules: true, // 指定启用css modules localIdentName: '[name]__[local]--[hash:base64:5]' // 指定css的类名格式 } } ] } ] } };
介绍之CSS预处理器
Sass
和 Less
之类的预处理器是对原生CSS的拓展,它们允许你使用类似于variables
, nesting
, mixins
, inheritance
等不存在于CSS中的特性来写CSS,CSS预处理器可以这些特殊类型的语句转化为浏览器可识别的CSS语句,
你现在可能都已经熟悉了,在Webpack
里使用相关load请输入代码
ers进行配置就可以使用了,以下是常用的CSS 处理Loaders
:
Less Loader
Sass Loader
Stylus Loader
4. 插件(Plugins)
插件(Plugins
)是用来拓展Webpack
功能的,它们会在整个构建过程中生效
注意Plugins
与Loaders
的区别:
Plugins
是在整个构建过程中生效的,拓展Webpack
功能的(比如压缩打包后的文件,添加版权声明等等)Loaders
是在文件打包过程中加入的外部脚本/工具,用于处理特殊的源文件(.vue
,JSX
,scss
,Less
)
上一份比较完整的conf代码:
// webpack.prd.config.js const webpack = require('webpack'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: __dirname + "/src/main.js", //已多次提及的唯一入口文件 output: { path: __dirname + "/dist", filename: "bundle.js" }, devtool: 'null', //注意修改了这里,这能大大压缩我们的打包代码 devServer: { contentBase: "./public", //本地服务器所加载的页面所在的目录 historyApiFallback: true, //不跳转 inline: true, hot: true }, module: { //Loaders配置 rules: [{ test: /(\.jsx|\.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ }, { test: /\.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: [{ loader: "css-loader", options: { modules: true } }, { loader: "postcss-loader" }], }) }] }, plugins: [ //插件配置 new webpack.BannerPlugin('版权所有,翻版必究'), new HtmlWebpackPlugin({ template: __dirname + "/app/index.tmpl.html" //new 一个这个插件的实例,并传入相关的参数 }), new webpack.HotModuleReplacementPlugin() //热加载插件 ], };
感谢zhangwang大佬的入门 Webpack,看这篇就够了,本篇学习攻略大部分来源于他的文章指导,感谢~