webpack的初步入门

语雀地址:https://www.yuque.com/chenzilong/mhtr5g/ygh2u8

目录

*. 写在开始

*.1 方式方法

*.2 阶段目标

*.3 本文的主线图

*.4 学习要求

1. 前端发展开始说起

1.1 发展历史

1.2 日益复杂的前端

1.3 包管理的发展

2. 前端为什么需要打包

3. 前端可选的打包工具对比

3.1 Grunt

3.2 Gulp

3.3 webpack 【webpack是什么?】

3.4 webpack和gulp,grunt的对比

4. webpack可以用来做什么【从零开始搭建简易webpack工程】

4.1 初始项目

4.2 js的处理:转换 ES6 代码,解决浏览器兼容问题

4.3 css的处理:编译css,抽取css到独立文件

4.4 html的处理:复制并压缩html文件

4.5 dist的清理:打包前清理源目录文件

4.6 assets的处理:静态资源处理

4.7 server的启用:development 模式下启动服务器并实时刷新

4.8 source-map本地查看源代码调试

4.9 eslint

4.10 前端开发过程中的代理处理

4.11 production处理

5. 服务构建环节理解

6. webpack的知识脑图


*. 写在开始

*.1 方式方法

学习开始前,要有一条主线去学习,还是要先思考一下,怎么去学习掌握webpack的知识。最好学习的路线是去使用它。学习webpack给自己定义的最终想要达到的结果是:

  1. 可以从无到有搭建一个前端脚手架项目,并且了解配置使用项。
  2. 通过webpack + ant design + [ dva / redux ] + react + react-router 搭建类ant design pro的项目出来。

*.2 阶段目标

  • 搞清楚webpack是什么,能给我们带来什么。
  • webpack的知识全局了解,然后绘制知识体系图
  • 根据知识体系图,放大单个的模块进行二次专研。
  • 串联知识体系内部各模块之间的知识联系和配合。
  • 从无到有搭建一个前端脚手架项目。
  • 搭建类ant design pro的项目出来【这个要设计其他知识体系的梳理,这个优先级放到最后】。
  • 延伸:webpack工作核心原理
  • 手动撸一个webpack简单基础版本去理解原理

*.3 本文的主线图

webpack的历史背景

文章思路 (1).png

 

*.4 学习要求

  1. 了解webpack相关的历史背景
  2. 建议webpack的学习路线
  3. 了解webpack与其他打包工具的对比
  4. 了解从零开始搭建一个小的webpack项目的过程
  5. 了解webpack的知识体系以及脑图

 

1. 前端发展开始说起

1.1 发展历史

1.1.1 原始社会

94年网景公司为了给科学家看文档,传论文推出的第一款浏览器,NCSAMosaic。当时的开发者统称为程序员。前端代码是后端代码的一部分:前端发送浏览器请求-》后端响应请求,发送静态页面-》返回到前端浏览器。

 

1.1.2 石器时代

94年php出现,将数据嵌入到html的形式,这好比是出现了一个方向,数据嵌入到模板中去。前端页面只是后端mvc中的V。

mvc模式:

  • Model(模型层):提供/保存数据。
  • Controller(控制层):数据处理,实现业务逻辑。
  • View(视图层):展示数据,提供用户界面。

 

以前的前端人员戏称为“切图仔”。因为后端太忙,没空写页面样式,于是就有了前端编写页面模板,让后端读物模板,替换变量,渲染出页面。

95年:网景推出了 Java,形成了前端的雏形:HTML 为骨架,CSS 为外貌,Java 为交互。

php将代码嵌入到html中

<html>
 <head>
  <title>Car {{ $car-&gt;id }}</title>
 </head> 
 <body> 
  <h1>Car {{ $car-&gt;id }}</h1> 
  <ul> 
   <li style="color:red">&gt;Make: {{ $car-&gt;make }}</li> 
   <li style="color:blue">Model: {{ $car-&gt;model }}</li> 
   <li style="color:yellow">Produced on: {{ $car-&gt;produced_on }}</li> 
  </ul> 
 </body>
</html>

java的jsp将数据嵌入到网页中

<html>
 <head>
  <title>Hello World</title>
 </head> 
 <body>
   Hello World!
  <br /> <% out.println(&quot;Your IP address is &quot; + request.getRemoteAddr()); %>  
 </body>
</html>

asp.net在html中嵌入c#代码

<html>
 <head></head>
 <body>
  @{ var imagePath=&quot;&quot;; if (Request[&quot;Choice&quot;] != null) {imagePath=&quot;images/&quot; + Request[&quot;Choice&quot;];} }    
  <h1>Display Images</h1> 
  <form method="post" action="">
    I want to see: 
   <select name="Choice"> <option value="Photo1.jpg">Photo 1</option> <option value="Photo2.jpg">Photo 2</option> <option value="Photo3.jpg">Photo 3</option> </select> 
   <input type="submit" value="Submit" /> @if (imagePath != &quot;&quot;) { 
   <p> <img src="@imagePath" alt="Sample" /> </p> } 
  </form>  
 </body>
</html>

 

1.1.3 铁器时代

98年ajax的应用ajax(Asynchronous Java And XML:异步的 Java 和 XML),也促进了web从1.0静态页面,纯内容展示想web2.0模式迈进。

Web 2.0 时代:动态网页,富交互,前端数据处理

06年:ajax被w3c正式纳入标准。

 

这时候前端已经不再仅仅是后端的模板,可以自己独立获取到数据。web 2.0由石器时代迈向了铁器时代。

06年用于操作DOM的jquery的出现,迅速成为了js库的第一位置。

 

1.1.4 工业时代

jquery直接操作dom的弊端渐渐体现出来,大量数据的今天,对dom的直接操作会导致页面性能比较差。

  • 2008 年,谷歌 V8 引擎发布,终结微软 IE 时代。
  • 2009 年 AngularJS 诞生、Node诞生。
  • 2011 年 React 诞生。
  • 2014 年 Vue.js 诞生。

Angular、React、Vue 等 MVVM 模式的出现,以及 Webpack 的前端工程化构建,加速了数据驱动前端工程化的发展。那么,Node 这个基于 V8 引擎的服务端 Java 运行环境的诞生,可媲美 Ajax 对于前端的贡献。

Node 是前端的第二次飞跃,它使 JS 在服务端语言中也有了一席之地。

如今,后端负责数据,前端负责其余工作越发明显化。它们之间的通讯,只需要后端暴露 RESTful 接口,前端通过 Ajax,以 HTTP 协议与后端通信即可。

 

1.1.5 小结

这一小结主要是了解前端发展的历史过程。看似和当前我们要讲的webpack没有什么关联,其实,每一个事情衍生都是有着它的历史原因。这里的历史原因还没讲到。前面就先当一个背景了解。

了解到了,ajax & node的出现对前端发展的冲击。

 

1.2 日益复杂的前端

从前一小节了解到了jquey & ajax。一旦前端应用需要从后端获取数据,就意味着前端应用在运行时是动态地渲染内容的,这便是Model(模型)UI层解耦。jQuery能够提供DOM操作方法和模型引擎等。这时的开发人员需要做下面两件事:

  • 动态生成HTML。由后端返回前端所需要的HTML,再动态替换页面的DOM页面。早期的典型架构如jQuery Mobile,事先在前端写好模板与渲染逻辑,用户的行为触发后台并返回对应的数据来渲染文件
  • 模板分离。由后端用API返回前端所需要的JSON数据,再由前端来计算生成这些HTML。

从node的诞生,前端很多时候的发展都是受到了后端的影响。类比java的spring mvc,c# asp.net mvc的思想,前端也出现了mv*的模式。从最早的knockout开始,后续出现的angular,vue,react。

发展到现在前端已经变得像后端一样复杂,已经从以前的web site到现在web app,开启了网站应用的SPA(single page application)的时代。现在已经是一个应用了。

 

前端应用的发展就好比则会出现很多个人或者团队的优秀的代码案例,类似与后台的maven包。前端因为node.js的发展

大量的Node.js使用者就建构了一个用NPM包管理工具管理的Node.js生态系统

 

1.3 包管理的发展

也是因为npm包的发展,促进了模块化开发的发展。

 

1.3.1 为什么模块很重要?

因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,没有规范则无法很好的一起玩耍了。

 

1.3.2 commonjs规范

在js发展的过程中,社区也在为JavaScript制定了相应的规范,其中CommonJS规范的提出算是最为重要的里程碑。在2009年8月,CommonJS诞生了。CommonJS规范为JavaScript制定了一个美好的愿景——希望JavaScript能够在任何地方运行。以达到像Python、Ruby和Java具备开发大型应用的基础能力,而不是停留在小脚本程序的阶段。

他们期望那些用CommonJS API写出的应用可以具备跨宿主环境执行的能力,这样不仅可以利用JavaScript开发富客户端应用,而且还可以编写以下应用,如服务器端JavaScript应用程序;命令行工具;桌面图形界面应用程序。 如今,CommonJS中的大部分规范虽然依旧是草案,但是已经初显成效,为JavaScript开发大型应用程序指明了一条非常棒的道路。目前,它依旧在成长中,这些规范涵盖了模块、二进制、Buffer、字符集编码、I/O流、进程环境、文件系统、套接字、单元测试、Web服务器网关接口、包管理等。

CommonJS是一种规范,业界有很多它的实现,其中最著名的是node.js

CommonJS定义的模块分为:{模块引用(require)} {模块定义(exports)} {模块标识(module)}

// package/lib is a dependency we require
var lib = require( "package/lib" );

// behaviour for our module
function foo(){
    lib.log( "hello world!" );
}

// export (expose) foo to other modules
exports.foo = foo;

 

1.3.3 AMD

基于commonJS规范的nodeJS出来以后,服务端的模块概念已经形成,很自然地,大家就想要客户端模块。而且最好两者能够兼容,一个模块不用修改,在服务器和浏览器都可以运行。

但是commonJs是为了后端的表现定制的规范,不适合前端。因为require的使用是同步的。这在后端没什么问题。但是浏览器肯定不行的。

所以AMD(异步模块定义)出现了,它就主要为前端JS的表现制定规范。

AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

RequireJS就是实现了AMD规范的呢

require([module], callback);

  // math.js
  define(function (){
    var add = function (x,y){
      return x+y;
    };

    return {
      add: add
    };
  });

  // main.js
  require(['math'], function (math){
    alert(math.add(1,1));
  });

 

1.3.4 CMD

玉伯写了seajs,就是遵循他提出的CMD规范,与AMD蛮相近的

// 所有模块都通过 define 来定义
define(function(require, exports, module) {

  // 通过 require 引入依赖
  var $ = require('jquery');
  var Spinning = require('./spinning');

  // 通过 exports 对外提供接口
  exports.doSomething = ...

  // 或者通过 module.exports 提供整个接口
  module.exports = ...

});

 

1.3.5 AMD & CMD的区别

作者:玉伯

链接:https://www.zhihu.com/question/20342350/answer/14828786

来源:知乎

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

RequireJS 和 SeaJS 都是很不错的模块加载器,两者区别如下:

1. 两者定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。SeaJS 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 服务器端

2. 两者遵循的标准有差异。RequireJS 遵循的是 AMD(异步模块定义)规范,SeaJS 遵循的是 CMD (通用模块定义)规范。规范的不同,导致了两者 API 的不同。SeaJS 更简洁优雅,更贴近 CommonJS Modules/1.1 和 Node Modules 规范。

3. 两者社区理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。SeaJS 不强推,而采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。

4. 两者代码质量有差异。RequireJS 是没有明显的 bug,SeaJS 是明显没有 bug。

5. 两者对调试等的支持有差异。SeaJS 通过插件,可以实现 Fiddler 中自动映射的功能,还可以实现自动 combo 等功能,非常方便便捷。RequireJS 无这方面的支持。

6. 两者的插件机制有差异。RequireJS 采取的是在源码中预留接口的形式,源码中留有为插件而写的代码。SeaJS 采取的插件机制则与 Node 的方式一致:开放自身,让插件开发者可直接访问或修改,从而非常灵活,可以实现各种类型的插件。还有不少细节差异就不多说了。

总之,SeaJS 从 API 到实现,都比 RequireJS 更简洁优雅。如果说 RequireJS 是 Prototype 类库的话,则 SeaJS 是 jQuery 类库。

最后,向 RequireJS 致敬!RequireJS 和 SeaJS 是好兄弟,一起努力推广模块化开发思想,这才是最重要的。

 

这里玉伯说了一句:“RequireJS 是没有明显的 bug,SeaJS 是明显没有 bug”。

版权归作者所有,任何形式转载请联系作者。

作者:U_U(来自豆瓣)

来源:https://www.douban.com/note/283566440/

SeaJS只会在真正需要使用(依赖)模块时才执行该模块

SeaJS是异步加载模块的没错, 但执行模块的顺序也是严格按照模块在代码中出现(require)的顺序

 

1.3.6 ECMASscript Module

// 报错
function f() {}
export f;

// 正确
export function f() {};

// 正确
function f() {}
export {f};
import { lastName as surname } from './profile.js';

export default 和 export的区别

// 第一组
export default function crc32() { // 输出
  // ...
}

import crc32 from 'crc32'; // 输入

// 第二组
export function crc32() { // 输出
  // ...
};

import {crc32} from 'crc32'; // 输入

 

1.3.7 webpack对模块规范的支持

以CommonJS来编写,但也支持AMD、CMD模块(对于新项目,推荐直接使用CommonJS)

 

2. 前端为什么需要打包

从上面的文章可以看到,前端发展到今天,有几个特征:

  • 前后端分离
  • 模块化开发
  • 包依赖开发
  • 前端已经从site发展成application

最主要的两个点:

  1. 前端项目已经是一个比较复杂的前端应用,并且是模块化开发,如果不进行打包的话,前端的资源请求会很多,性能会比较差。
  2. 编译,目前前端js的语言还不是浏览器能够完全支持的,ES6,jsx,saas等高级语法还需要进行编译转换。而且三大框架的语法还是需要对应编译才可以在浏览器里运行,编译也是必须的。

 

3. 前端可选的打包工具对比

3.1 Grunt

Grunt是一个任务执行者,有大量现成的插件封装了常见的任务,也能管理任务之间的依赖关系,自动化执行依赖的任务,每个任务的具体执行代码和依赖关系写在配置文件 Gruntfile.js

Grunt的优点

  • 灵活,它只负责执行你定义的任务;
  • 大量的可复用插件封装好了常见的构建任务。

Grunt的缺点

集成度不高,要写很多配置后才可以用,无法做到开箱即用。

 

3.2 Gulp

Gulp 是一个基于流的自动化构建工具。 除了可以管理和执行任务,还支持监听文件、读写文件。Gulp 被设计得非常简单,只通过下面5种个方法就可以胜任几乎所有构建场景。

  • 通过 gulp.task 注册一个任务;
  • 通过 gulp.run 执行任务;
  • 通过 gulp.watch 监听文件变化;
  • 通过 gulp.src 读取文件;
  • 通过 gulp.dest 写文件。

Gulp 的优点是好用又不失灵活,既可以单独完成构建也可以和其它工具搭配使用。其缺点是和 Grunt 类似,集成度不高,要写很多配置后才可以用,无法做到开箱即用。

可以将Gulp 看作 Grunt 的加强版。相对于 Grunt,Gulp增加了监听文件、读写文件、流式处理的功能。

 

3.3 webpack 【webpack是什么?】

image.png

官方解释:是一个打包模块化 JavaScript 的工具,在 Webpack 里一切文件皆模块,通过 Loader 转换文件,通过 Plugin 注入钩子,最后输出由多个模块组合成的文件。Webpack 专注于构建模块化项目。

https://blog.csdn.net/zlzbt/article/details/104813855

  • 一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。webpack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其他的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。
  • Webpack 是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。通过 loader 的转换,任何形式的资源都可以视作模块,比如 CommonJs 模块、 AMD 模块、 ES6 模块、CSS、图片、 JSON、Coffeescript、 LESS 等。
  • 模块化开发中,我们会编写大量模块,如果不打包就进行上线,那么页面加载或交互时,将会发起大量的请求。为了性能优化,需要使用webpack这样的打包器对模块进行打包整合,以减少请求数。就像简单的react项目,所有组件最终将被打包到一个app.js中。较于无差别打包依赖模块的传统打包器(Grunt和Gulp等),webpack的核心优势在于它从入口文件出发,递归构建依赖关系图。通过这样的依赖梳理,webpack打包出的bundle不会包含重复或未使用的模块,实现了按需打包,极大的减少了冗余

webpack可以很好的支持模块化开发,从项目的角度去构建前端工程化,可以做性能优化,按需打包,处理不同的资源。相比gulp,grant来说,维度处于更高的一个层级,从整个项目的维度。webpack的打包机制也是完美的契合前端页面加载,依赖的关系。前端的页面加载都会有初始页面,相当于初始入口。前端页面的加载顺序就是初始文件,然后加载对应文件的依赖文件。

 

3.4 webpack和gulp,grunt的对比

3.4.1 Grunt Gulp NPM脚本的比较

Tobias(webpack作者): NPM脚本对我而言足矣。实际上,说webpack是Grunt/Gulp的替代器并不完全准确。Grunt和Gulp以及NPM脚本都是任务执行程序。

Webpack是_模块打包程序_。这两类程序的目标不一样。但webpack简化了必须“过度使用”Grunt和Gulp和NPM脚本才能实现的Web开发任务也是事实。NPM脚本才是Grunt和Gulp的替代品。

image.png

不过,除了纯粹的构建之外,任务运行程序也有存在的理由,比如部署、代码检查、版本管理,等等。

 

3.4.2 Webpack与Grunt、Gulp运行机制

# grunt gulp 思路

【遍历源文件】->【匹配规则】->【打包】

做不到按需加载,对打包的资源,是否用到,打包过程不关心。

# webpack

【入口】->【模块依赖加载】->【依赖分析】->【打包】

在加载、分析、打包的过程中,可以针对性的做一些解决方案。比如:code split(拆分公共代码)

 

3.4.3 总结

  • gulp,grunt是web构建工具
  • webpack是模块化方案
  • gulp,grunt是基于任务和流
  • webpack基于入口文件
  • Grunt和Gulp的工作方式是:在一个配置文件中,指明对某些文件进行类似编译,组合,压缩等任务的具体步骤,工具之后可以自动替你完成这些任务。
  • Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。

 

4. webpack可以用来做什么【从零开始搭建简易webpack工程】

代码地址:https://github.com/rodchen-king/wepack-learn

4.1 初始项目

github地址

npm init -y       

npm install webpack webpack-cli --save-dev

npm install --save-dev style-loader css-loader
module: {
    // loader
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      }
    ]
  }

 

4.2 js的处理:转换 ES6 代码,解决浏览器兼容问题

webpack4.44.1 似乎内部封装了babel-loader

github代码地址

npm install babel-loader@8.0.0-beta.0 @babel/core @babel/preset-env webpack
{
    test: /\.js$/,
    exclude: /(node_modules|bower_components)/,  // node_modules 目录或者其他不需要编译的源代码 
    use: {
      loader: 'babel-loader',
      options: {
        presets: [['@babel/preset-env', {       // 预设环境进行编译js,可以加入参数 https://www.jianshu.com/p/000c2670672b
          "targets": {
            "browsers": [
              "Firefox > 86"
            ]
          }
        }]]
      }
    }
  }

 

4.3 css的处理:编译css,抽取css到独立文件

github地址

npm install --save-dev mini-css-extract-plugin
module: {
    // loader
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin(),
  ]

 

4.4 html的处理:复制并压缩html文件

github代码地址

npm install --save-dev html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');

plugins: [
  new HtmlWebpackPlugin()
]

 

4.5 dist的清理:打包前清理源目录文件

github代码地址

npm install --save-dev clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

plugins: [
    new CleanWebpackPlugin()
]

 

4.6 assets的处理:静态资源处理

github代码地址

npm install --save-dev file-loader
npm install --save-dev csv-loader xml-loader
rules: [
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader'
        ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          'file-loader'
        ]
      },
      {
        test: /\.(csv|tsv)$/,
        use: [
          'csv-loader'
        ]
      },
      {
        test: /\.xml$/,
        use: [
          'xml-loader'
        ]
      }
    ]

 

4.7 server的启用:development 模式下启动服务器并实时刷新

github代码地址

npm install --save-dev webpack-dev-server
module.exports = {
  devServer: {
    contentBase: './dist'
   }
}
"scripts": {
  "start": "webpack-dev-server --open",
  "test": "echo \"Error: no test specified\" && exit 1",
  "build": "webpack"
}

 

4.8 source-map本地查看源代码调试

github代码地址

module.exports = {
  devtool: 'inline-source-map'
}

image.png

image.png

 

4.9 eslint

github代码地址

npm install eslint-loader --save-dev
npm install eslint --save-dev
npm install eslint-friendly-formatter --save
rules: [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: 'eslint-loader',
    include: [path.resolve(__dirname, 'src')],        // 指定检查的目录
    options: {                                        // 这里的配置项参数将会被传递到 eslint 的 CLIEngine
      formatter: require('eslint-friendly-formatter') // 指定错误报告的格式规范,formatter默认是stylish,如果想用第三方的要另外安装
    }
  }
}
module.exports = {
  'root': true,
  'plugins': [
      'html'
  ],
  'settings': {
      'html/html-extensions': ['.wxml']
  },
  'rules': {
      'newline-per-chained-call': 'off',
      'eqeqeq': 'off',
      'indent': ['error', 4, { SwitchCase: 1 }],
      'prefer-rest-params': 'off',
      'prefer-template': 'off',
      'array-callback-return': 'off',  // 暂时关闭
      'prefer-const': 'warn',
     
      'no-restricted-properties': [2, {
          'object': 'wx',
          'property': 'navigateTo',
          'message': 'Please use this.$goto!!!'
      }]
  }
}

image.png

 

4.10 前端开发过程中的代理处理

github代码地址

module.exports = {
  devServer: {
    proxy: {
      '/api': 'http://localhost:3000'
    }
  }
}

 

4.11 production处理

4.11.1 拆分dev和prd的webpack配置文件

github代码地址

npm install --save-dev webpack-merge
// webpack.commom.js 

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
  entry: './src/index.js',     // 相对根目录路径
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, '../dist')
  },
  module: {
    // loader
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,  // node_modules 目录或者其他不需要编译的源代码 
        use: {
          loader: 'babel-loader',
          options: {
            presets: [['@babel/preset-env', {       // 预设环境进行编译js,可以加入参数 https://www.jianshu.com/p/000c2670672b
              "targets": {
                "browsers": [
                  "Firefox > 86"
                ]
              }
            }]]
          }
        }
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'eslint-loader',
        include: [path.resolve(__dirname, 'src')],        // 指定检查的目录
        options: {                                        // 这里的配置项参数将会被传递到 eslint 的 CLIEngine
          formatter: require('eslint-friendly-formatter') // 指定错误报告的格式规范,formatter默认是stylish,如果想用第三方的要另外安装
        }
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader'
        ]
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: [
          'file-loader'
        ]
      },
      {
        test: /\.(csv|tsv)$/,
        use: [
          'csv-loader'
        ]
      },
      {
        test: /\.xml$/,
        use: [
          'xml-loader'
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin(),
    new HtmlWebpackPlugin(),
    new CleanWebpackPlugin()
  ]
};
// webpack.dev.js & webpack.prd.js

const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
  devtool: 'inline-source-map',
  devServer: {
    contentBase: '../dist',
    proxy: {
      '/api': 'http://localhost:3000'
    }
   },
});
// package.json

"scripts": {
  "start": "webpack-dev-server --open --config ./config/webpack.dev.js",
  "test": "echo \"Error: no test specified\" && exit 1",
  "build": "webpack --config ./config/webpack.prd.js"
},
 

4.11.2 prd处理,代码压缩 & 提取公共代码

github代码地址

npm i -D uglifyjs-webpack-plugin
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

module.exports = merge(common, {
  devtool: 'source-map',
  output: {
    chunkFilename: '[name].[chunkhash:8].js'
  },
  devServer: {
    contentBase: '../dist',
    proxy: {
      '/api': 'http://localhost:3000'
    }
   },
   optimization: {
    splitChunks: {
    cacheGroups: {
        vendor: {
            test: /[\\/]node_modules[\\/]/,
            name: 'common',
            chunks: 'all'
        }
    }
    }
  },
   plugins: [
    new UglifyJsPlugin()
  ]
});

 

5. 服务构建环节理解

  • 如果与输入相关的需求,找entry(比如多页面就有多个入口)
  • 如果与输出相关的需求,找output(比如你需要定义输出文件的路径、名字等等)
  • 如果与模块寻址相关的需求,找resolve(比如定义别名alias)
  • 如果与转译相关的需求,找loader(比如处理sass处理es678N)
  • 如果与构建流程相关的需求,找plugin(比如我需要在打包完成后,将打包好的文件复制到某个目录,然后提交到git上)

 

6. webpack的知识脑图

📎webpack脑图 (1).xmind

脑图地址:https://www.processon.com/view/link/5f59849ee0b34d6f59ea4fa4

webpack脑图.jpg

 

参考文章:

https://www.webpackjs.com/concepts/

https://cnblogs.com/LuckyWinty/p/10116497.html

https://www.sohu.com/a/282933022_661296

https://www.cnblogs.com/moxiaowohuwei/p/8692359.html

https://www.zhihu.com/question/20342350

https://blog.csdn.net/qiuxi4057/article/details/80846595

https://blog.csdn.net/zlzbt/article/details/104813855

https://segmentfault.com/a/1190000015973544

https://www.cnblogs.com/LuckyWinty/p/10116497.html

 

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页