一、前言

  不知不觉,webpack版本已经到4.0了。使用它也有很长一段时间了,回头看看,自己木有总结webpack方面的知识,现在有空起个头,主要是总结自己常用的配置和一下优化的探讨,以后有啥想法也直接写到这里来。

二、开始

  webpack做啥的,怎么配置?和gulp、grunt等构件工具有什么区别?这些就跳过了,当初也是直接看官方文档的,摸爬滚打走过来的。可以参考:

  1、https://www.webpackjs.com/

  2、《入门 Webpack,看这篇就够了》

  3、《vue-cli中webpack配置》系列

4 《webpack持久化缓存实践

5 、 https://www.jianshu.com/p/b9bf995f3712

6、《解决疑惑,让你明白》

三、实际项目中解析

3.1、本项目支持的功能

  1. 1 less编译
  2. 2 支持es6语法支持
  3. 3 编译.vue组件,并自动内联组件样式
  4. 4 图片打包,包括对html内图片处理(利用html-loaderes6字符串模板),对小图片生成base64
  5. 5 利用htmlWebpackPlugin动态拼接html 的公共部分和内容部分,引入相应css/js资源,并构建到指定目录, ejs模板支持
  6. 6 js内依赖的css分离并压缩
  7. 7 js引用的公共模块抽取分离成单独文件
  8. 8 区分开发环境和生产环境
  9. 9 js 压缩
  10. 10 静态文件(css/js/imghash版本支持
  11. 11 清除目标文件目录
  12. 12 eslint支持并实现自动修复部分问题
  13. 13 vue接口请求axios支持
  14. 14 热更新,自动编译并刷新浏览器

3.2、目录结构

  1. |__ html
  2. |__ dist
  3. |__ income.html
  4. |__ index.html
  5. |__ src
  6. |__ income
  7. |__ income.ejs
  8. |__ income.js
  9. |__ index
  10. |__ index.ejs
  11. |__ index.js
  12. |__ layouts
  13. |__ footer.ejs
  14. |__ header.ejs
  15. |__ layout.ejs
  16. |__ layout.js
  17. |__ side-menu.e
  18. |__ top-nav.ejs
  19. |__ dist
  20. |__ css
  21. |__ img
  22. |__ js
  23. |__ income.js
  24. |__ index.js
  25. |__ manifest.js
  26. |__ vendors.js
  27. |__ src
  28. |__ css
  29. |__ img
  30. |__ js
  31. |__ component
  32. |__ App.vue
  33. |__ income.js
  34. |__ index.js
  35. |__ lib
  36. |__ axios.min.js
  37. |__ layer.js
  38. |__ vue.js
  39. |__ vue.min.js
  40. |__ mock
  41. |__ node_modules
  42. |__ webpack-config
  43. |__ .eslintrc.dev.js
  44. |__ .eslintrc.js
  45. |__ postcss.config.js
  46. |__ resolve.config.js
  47. |__ package.json
  48. |__ .babelrc
  49. |__ .eslintrc.js

四、入口entry

  1. var entries = getEntry('./src/**/*.js') // 获得入口js文件
  2. entries.vendors = ['vue','axios']
  3.  
  4. module.exports = {
  5. /* 输入文件 */
  6. entry: entries
  7. } 

通常我们的项目中有大量的js入口文件,基本一个功能页面有一个js,这时我们的 entry 文件为一个对象格式

  1. entries 为:
  2.  
  3. {
  4. income: './src/js/income.js',
  5. index: './src/js/index.js',
  6. vendors: [ 'vue', 'axios' ]
  7. }

key 值为对应模块的别名,webpack会依次处理这些模块。

vendors 为公共模块,这里我们把vue, axios设置为公共模块,供下面进行提取公共模块操作。

之所以可以直接写vue, axios,是因为我们在 alias 里设置了别名:

  1. var path = require('path')
  2.  
  3. module.exports = {
  4. // 模块别名的配置,为了使用方便,一般来说所有模块都是要配置一下别名的
  5. alias: {
  6. 'vue': path.resolve(__dirname, '../src/js/lib/vue.min.js'),
  7. 'axios': path.resolve(__dirname, '../src/js/lib/axios.min.js')
  8. }
  9. } 

这里的 path.resolve 作用是把相对路径转为绝对路径,假设我项目建在d:/demo 目录下,

  1. _dirname: d:\demo
  2.  
  3. path.resolve(__dirname, '../src/js/lib/vue.min.js'): d:\demo\src\js\lib\vue.min.js

getEntry() 为获取文件路径的自定义函数:

  1. /***** 获取文件列表:输出正确的js和html路径 *****/
  2. var glob = require('glob')
  3.  
  4. function getEntry(globPath) {
  5. var entries = {}, basename
  6.  
  7. glob.sync(globPath).forEach(function (entry) {
  8. //排出layouts内的公共文件
  9. if(entry.indexOf('layouts') == -1 && entry.indexOf('lib') == -1){
  10. basename = path.basename(entry, path.extname(entry))
  11. entries[basename] = entry
  12. }
  13. })
  14. return entries
  15. } 

通常webpack的entry入口文件,是功能性页面的js,对于js库等文件不需要列入入口文件进行处理。所以这里对lib文件夹进行了排除。layouts文件夹为获取html路径时需要排除的文件路径。  

五、output介绍

  1. module.exports = {
  2. output: {
  3. /* 输出目录,没有则新建 */
  4. path: path.resolve(__dirname, './dist'),
  5. /* 静态目录,可以直接从这里取文件 */
  6. publicPath: 'http://www.xxx.com/dist/',
  7. /* 文件名 */
  8. filename: 'js/[name].js?v=[chunkhash:8]'
  9. }
  10. }

 publicPath: 如果有这项,则html中的引用的js路径会加上publicPath,即 http://www.xxx.com/dist/js/[name].js?v=[chunkhash:8]

 filename: 这里可以自定义输出后的文件名,加上版本号

  [name] :输入模块的别名

  [chunkhash] : 模块的hash值,":8"代表保留8位hash值

  [hash] : 整个编译环境的hash值

hash和chunkhash具体区别请看这里

六、module介绍

Webpack有一个不可不说的优点,它把所有的文件都都当做模块处理,JavaScript代码,CSS和fonts以及图片等等通过合适的loader都可以被处理。

webpack利用各种loader来把不同格式的文件封装成模块加载到js内,比如css-loader, vue-loader,下面,只列举一部分。

6.1、babel-loader

es6语法目前很多浏览器不支持,我们需要将其转化为大部分浏览器支持的es5语法,这就需要babel-loader

  1. {
  2. test: /\.js$/,
  3. loader: 'babel-loader',
  4. exclude: ['node_modules','./src/js/lib','./src/js/component']
  5. }

  

6.2、 css有关的loader

css-loader style-loader post-loader less-loader

  1. {
  2. test: /\.css$/,
  3. use: ['style-loader', 'css-loader', 'postcss-loader']
  4. },
  5. {
  6. test: /\.less$/,
  7. use: ExtractTextPlugin.extract(['css-loader','postcss-loader','less-loader'])
  8. }

  

对于有多个loader时,webpack v2也废弃了v1的 " !" 连接,改为数组形式,且不能省略 " -loader " 以免造成名称混乱意思模糊,执行顺序为从右到左

postcss-loader:为集合处理css各种问题的平台,其上面有各种插件来处理css,我们这里只用到了autoprefixer插件,后面插件部分会详解

style-loader:可以将css以style内联方式嵌入到html页面

css-loader:使你能够使用类似@import 和 url(...)的方法实现 require()的功能

ExtractTextPlugin:提取css, 后面插件部分会进行详解

6.3、css module:

把JS的模块化思想带入CSS中来,通过CSS模块,所有的类名,动画名默认都只作用于当前模块。Webpack对CSS模块化提供了非常好的支持,只需要在CSS loader中进行简单配置即可,然后就可以直接把CSS的类名传递到组件的代码中,这样做有效避免了全局污染。具体的代码如下:

  1. module.exports = {
  2.  
  3. ...
  4.  
  5. module: {
  6. rules: [
  7. {
  8. test: /(\.jsx|\.js)$/,
  9. use: {
  10. loader: "babel-loader"
  11. },
  12. exclude: /node_modules/
  13. },
  14. {
  15. test: /\.css$/,
  16. use: [
  17. {
  18. loader: "style-loader"
  19. }, {
  20. loader: "css-loader",
  21. options: {
  22. modules: true, // 指定启用css modules
  23. localIdentName: '[name]__[local]--[hash:base64:5]' // 指定css的类名格式
  24. }
  25. }
  26. ]
  27. }
  28. ]
  29. }
  30. };

6.4、文件图片loader

  1. {
  2. test: /\.(png|jpg|gif)$/,
  3. loader: 'url-loader?limit=5120&name=img/[name].[ext]?v=[hash:8]'
  4. }

6.5、字体loader

  1. {
  2.   test: /\.(ttf|ttc|eot|svg|woff(2))$/,
  3. loader: 'file-loader',
  4. options:{
  5. name: function(p){
  6. let tem_path = p.split(/\\fonts\\/)[1];
  7. tem_path = tem_path.replace(/\\/g,'/');
  8. return 'fonts/'+tem_path + '?v=[hash:8]';
  9. }
  10. }
  11. }

    

七、插件plugin

插件是用来拓展Webpack功能的,它们会在整个构建过程中生效,执行相关的任务。
Loaders和Plugins常常被弄混,但是他们其实是完全不同的东西,可以这么来说,loaders是在打包构建过程中用来处理源文件的(JSX,Scss,Less..),一次处理一个,插件并不直接操作单个文件,它直接对整个构建过程其作用。

使用方法一般如下:

  1. module: {},
  2. plugins: [
  3. new ExtractTextPlugin('css/[name].css?v=[contenthash:6]'),
  4. new webpack.LoaderOptionsPlugin({
  5. options: {
  6. eslint: require( './webpack-config/.eslintrc.js'),
  7. postcss: require( './webpack-config/postcss.config.js')
  8. },
  9. })
  10. ]  

webpack声明插件的方式可以像上面的写法也可以如下方式:

  1. module.exports.plugins = module.exports.plugins.concat([
  2. //压缩css代码
  3. new OptimizeCssAssetsPlugin({
  4. assetNameRegExp: /\.css/g,
  5. cssProcessor: require('cssnano'),
  6. cssProcessorOptions: { discardComments: {removeAll: true } },
  7. canPrint: true
  8. }),
  9. //压缩JS代码
  10. new webpack.optimize.UglifyJsPlugin({
  11. output: {
  12. comments: false, // 去掉注释内容
  13. }
  14. })
  15. ]) 

7.1、extract-text-webpack-plugin 插件

默认情况下,js依赖引入css,编译后,css被加在js中,如果我们想把css提取出一个单独的文件,可以使用这个插件,并可以对提取出的css进行自定义命名和加版本hash值

  1. new ExtractTextPlugin('css/[name].[contenthash:8].css'),

7.2、optimize-css-assets-webpack-plugin 插件

压缩css文件,对从js中提取出的css文件亦有效

注意:此插件是在css被提取出来加了hash值后进行处理,如果css文件提出来后被命名为  css/[name].css?v=[contenthash:8] 形式,插件的使用如下

  1. new OptimizeCssAssetsPlugin({
  2. assetNameRegExp: /\.css/g, //注意不要写成 /\.css$/g, 否则匹配不到css文件会导致压缩不成功
  3. cssProcessor: require('cssnano'),
  4. cssProcessorOptions: { discardComments: {removeAll: true } },
  5. canPrint: true
  6. })

7.3、webpack-plugin 插件

用于根据模板组合html各个部分,并插入对应引用的js,对前后端分离贡献颇多,功能强大会有专门的篇章来介绍

7.4、CommonsChunkPlugin 插件

 提取js的公共模块,此插件为webpack自带的插件

  1. new webpack.optimize.CommonsChunkPlugin({
  2. names: ['vendors', 'manifest'], // 公共模块的名称
  3. //filename: 'js/[name]-[chunkhash:6].js', // 公共模块的名称
  4. chunks: 'vendors', // chunks是需要提取的模块
  5. minChunks: Infinity //公共模块最小被引用的次数
  6. }) 

  通常我们的js可能会引入一些公共js文件,包括一些类库,如果都打包在一个js中,这个js会变得非常庞大,而且一旦我们功能页面的js有变化,会导致打包后的js版本号进行更新然后重新加载,这个代价有些大,所以我们会考虑把一些公共的js文件提取出一个单独的文件,这样在第一次访问的时候会加载,之后就可以缓存下来,减少服务器请求的压力并提高加载速度。  

7.5 CleanWebpackPlugin插件

保证买次编译之后目标文件中只保留最新的文件

  1. new CleanWebpackPlugin(['dist']) 

------------有时间再添加了------------

八、一些优化探索

 

 

  

关于wepack的使用总结以及优化探讨的更多相关文章

  1. CSS性能优化探讨

    大部分前端开发人员都不关心CSS性能优化,其实对于一个复杂的页面来说,高效的选择器还是可以带来一定的性能提升的. 1. CSS 选择器 浏览器是“从右往左”来分析 class 的,它的匹配规则是从右向 ...

  2. Webpack 打包之体积优化

    谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...

  3. [转] Webpack 打包优化之体积篇

    谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...

  4. Webpack 打包优化之体积篇

    谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...

  5. Python Flask高级编程之RESTFul API前后端分离精讲 (网盘免费分享)

    Python Flask高级编程之RESTFul API前后端分离精讲 (免费分享)  点击链接或搜索QQ号直接加群获取其它资料: 链接:https://pan.baidu.com/s/12eKrJK ...

  6. System.out.printf使用以及注意点

    一.System.out.printf格式化输出 1.常用控制符 控制符 说明 %d 按十进制整型数据的实际长度输出. %ld 输出长整型数据. %md m 为指定的输出字段的宽度.如果数据的位数小于 ...

  7. 《MySQL必知必会》学习笔记——第30章 改善性能

    本章将付息与MySQL性能有关的某些要点. 30.1 改善性能 数据库管理员把他们生命中的相当一部分时间花在了调整.试验以改善DBMS性能之上.在诊断英勇的滞缓现象和性能问题时,性能不良的数据库(以及 ...

  8. 【MySQL 基础】MySQL必知必会

    MySQL必知必会 简介 <MySQL必知必会>的学习笔记和总结. 书籍链接 了解SQL 数据库基础 什么是数据库 数据库(database):保存有组织的数据的容器(通常是一个文 件或一 ...

  9. 移动 H5 首屏秒开优化方案探讨

    转载bang大神文章,原文<移动 H5 首屏秒开优化方案探讨>,此文仅仅用做自学与分享! 随着移动设备性能不断增强,web 页面的性能体验逐渐变得可以接受,又因为 web 开发模式的诸多好 ...

随机推荐

  1. Scanner 随机数

    import java.util.Scanner;                                               import java.util.Scanner; Sc ...

  2. 转载-js如何设置网页横屏和竖屏切换

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  3. 【Mybatis】MyBatis配置文件的使用(二)

    本例在[Mybatis]MyBatis快速入门(一)基础上继续学习XML映射配置文件 MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置(settings)和属性(properti ...

  4. 小米open-falcon监控系统接入手册

    一.新项目接入 0.官方文档: https://book.open-falcon.org/zh_0_2/usage/getting-started.html 1.联系运维人员确定可以使用监控系统: ( ...

  5. VUE 动态给对象增加属性,并触发视图更新。

    在开发过程中,我们时常会遇到这样一种情况:当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的. 根据官方文档定义 ...

  6. java安装jdk错误1316 指定的账户已存在

    java安装jdk错误1316 指定的账户已存在 处理步骤: 1.卸载jdk,成功后重启 2.删除注册表中文件夹 (1)\HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft文件夹 ...

  7. python_day1_变量

    一.变量 定义: 通俗来讲可变化的量称之为变量,专业的解释为:把程序运算的中间结果临时存到内存里,以备后面的代码继续调用,这几个名字的学名就叫做“变量” 用法: name = 'zzx' 其中name ...

  8. GDB基础学习

    GDB基础学习 要调试C/C++程序,首先在编译时,我们必须要把调试信息加到可执行文件中.使用编译器(cc/gcc/g++)的-g参数可以做到这一点,比如: gcc -g test.c -o test ...

  9. 源码解读Linux的limits.conf文件

    目录 目录 1 1. 前言 1 2. PAM 2 3. pam_limits 2 4. limits.conf的由来 3 5. 模块入口函数 4 6. 解析limits.conf 6 7. 生效lim ...

  10. winSCP无法连接虚拟机Linux解决

    刚在虚拟机上装上Linux(Centos7)后使用winSCP建立文件共享发现连接超时,经过几个小时的查找发现Linux中没有eth0文件,这说明其网卡名不是eth0,在网上查过一些解决办法有的通过修 ...