<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>IT梅的前端经验分享</title>
  
  <subtitle>一个前端从业者，喜欢新技术</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://www.meixiaohan.com/"/>
  <updated>2020-06-03T09:13:25.799Z</updated>
  <id>http://www.meixiaohan.com/</id>
  
  <author>
    <name>IT梅</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>一文带你了解js数据储存及深复制（深拷贝）与浅复制(浅拷贝)</title>
    <link href="http://www.meixiaohan.com/2020/06/03/js/deepClone/"/>
    <id>http://www.meixiaohan.com/2020/06/03/js/deepClone/</id>
    <published>2020-06-02T16:00:00.000Z</published>
    <updated>2020-06-03T09:13:25.799Z</updated>
    
    <content type="html"><![CDATA[<h2 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h2><p>在日常开发中，偶尔会遇到需要复制对象的情况，需要进行对象的复制。</p><p>由于现在流行标题党，所以，一文带你了解js数据储存及深复制（深拷贝）与浅复制(浅拷贝)</p><h2 id="理解"><a href="#理解" class="headerlink" title="理解"></a>理解</h2><p>首先就需要理解 js 中的数据类型了<br>js 数据类型包含</p><ol><li><code>基础类型</code>:<code>String</code>、<code>Number</code>、 <code>null</code>、<code>undefined</code>、<code>Boolean</code>以及<code>ES6</code>引入的<code>Symbol</code>、<code>es10</code>中的<code>BigInt</code></li><li><code>引用类型</code>:<code>Object</code></li></ol><p>由于 js 对变量的储存是<code>栈内存</code>、<code>堆内存</code>完成的。</p><ul><li><code>基础类型</code>将数据保存在<code>栈内存</code>中</li><li><code>引用类型</code>将数据保存在<code>堆内存</code>中</li></ul><p>由于 js 在数据读取和写入的时候，对<code>基础类型</code>是直接读写<code>栈内存</code>中的数据，<code>引用类型</code>是将一个内存地址保存在栈内存中，读写都是修改栈内存中指向堆内存的地址</p><p>以如下代码为例</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">let obj = &#123;</span><br><span class="line">  a:1,</span><br><span class="line">  arr:[1,3,5,7,9],</span><br><span class="line">  b:2,</span><br><span class="line">  c:&#123;</span><br><span class="line">    num:100</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">let num = 10</span><br></pre></td></tr></table></figure><p>在内存中的表现为<br><img src="https://imgkr.cn-bj.ufileos.com/08889b21-612d-44c1-916a-ff97e0b3adc2.jpg" alt="内存中的展示"></p><p>我们声明个obj1</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let obj1 = obj;</span><br><span class="line">console.log(obj1 == obj);//true</span><br></pre></td></tr></table></figure><p>因为这个赋值，把内存变成了这样</p><p><img src="https://imgkr.cn-bj.ufileos.com/cb8c3a11-9194-477f-94af-d8627679343a.jpg" alt="赋值后"></p><p>然后，内存中只是给js栈内存新增了一个指向<code>堆内存</code>的地址而已，这种就叫做<code>浅复制</code>。因为如图可以看到，如果我们修改<code>obj.a</code>的话，实际修改的是<code>堆内存0x88888888</code>中的<code>变量a</code>，由于<code>obj1</code>也指向这个地址，所以<code>obj1.a</code>也被修改了</p><p><code>深复制</code>是指，不单单复制引用地址，连堆内存都复制一遍，使<code>obj</code>和<code>obj1</code>不指向同一个地址。</p><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><p>分开来看<code>深复制</code>与<code>浅复制</code></p><h3 id="浅复制"><a href="#浅复制" class="headerlink" title="浅复制"></a>浅复制</h3><p>由上述图可知，浅复制只是复制第一层，也就是，<code>基本类型</code>复制新值，<code>引用类型</code>复制引用地址</p><p><code>浅复制</code>可以使用的方案有<code>循环赋值</code>、<code>扩展运算符</code>、<code>object.assign()</code>,</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">let obj = &#123;</span><br><span class="line">  a:1,</span><br><span class="line">  arr:[1,3,5,7,9],</span><br><span class="line">  b:2,</span><br><span class="line">  c:&#123;</span><br><span class="line">    num:100</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">function clone1(obj)&#123; // 使用循环赋值</span><br><span class="line">  let b = &#123;&#125;;</span><br><span class="line">  for(let key in obj)&#123;</span><br><span class="line">    b[key] = obj[key]</span><br><span class="line">  &#125;</span><br><span class="line">  return b</span><br><span class="line">&#125;</span><br><span class="line">function clone2(obj)&#123; // 使用扩展运算符</span><br><span class="line">  let b = &#123;</span><br><span class="line">    ...obj</span><br><span class="line">  &#125;;</span><br><span class="line">  return b</span><br><span class="line">&#125;</span><br><span class="line">function clone3(obj)&#123; // 使用object.assign()</span><br><span class="line">  let b = &#123;&#125;;</span><br><span class="line">  Object.assign(b,obj)</span><br><span class="line">  return b</span><br><span class="line">&#125;</span><br><span class="line">let obj1 = clone1(obj);</span><br><span class="line">let obj2 = clone2(obj);</span><br><span class="line">let obj3 = clone3(obj);</span><br><span class="line"></span><br><span class="line">console.log(obj1 === obj); //false 代表复制成功了</span><br><span class="line">console.log(obj2 === obj); //false 代表复制成功了</span><br><span class="line">console.log(obj3 === obj); //false 代表复制成功了</span><br><span class="line">console.log(&apos;obj0.c.num修改前&apos;,obj.c.num); //100</span><br><span class="line">console.log(&apos;obj1.c.num修改前&apos;,obj1.c.num); //100</span><br><span class="line">console.log(&apos;obj2.c.num修改前&apos;,obj2.c.num); //100</span><br><span class="line">console.log(&apos;obj3.c.num修改前&apos;,obj3.c.num); //100</span><br><span class="line">obj0.c.num = 555;</span><br><span class="line">console.log(&apos;obj0.c.num修改后&apos;,obj.c.num); //555</span><br><span class="line">console.log(&apos;obj1.c.num修改后&apos;,obj1.c.num); //555</span><br><span class="line">console.log(&apos;obj2.c.num修改后&apos;,obj2.c.num); //555</span><br><span class="line">console.log(&apos;obj3.c.num修改后&apos;,obj3.c.num); //555</span><br></pre></td></tr></table></figure><p>由于是浅复制，所以引用类型只是复制了内存地址，修改其中一个对象的子属性后，引用这个地址的值都会被修改。</p><p>浅克隆图解如下<br><img src="https://imgkr.cn-bj.ufileos.com/c16e076a-d152-4b50-bd48-8055fa56cd29.jpg" alt="浅克隆图解"></p><h3 id="深复制"><a href="#深复制" class="headerlink" title="深复制"></a>深复制</h3><p>由于浅复制只是复制第一层，为了解决引用类型的复制，需要使用深复制来完成对象的复制，<code>基本类型</code>复制新值，<code>引用类型</code>开辟新的<code>堆内存</code>。</p><p><code>深复制</code>可以使用的方案有<code>JSON.parse(JSON.stringify(obj))</code>、<code>循环赋值</code>。</p><h4 id="JSON-parse-JSON-stringify-obj"><a href="#JSON-parse-JSON-stringify-obj" class="headerlink" title="JSON.parse(JSON.stringify(obj))"></a>JSON.parse(JSON.stringify(obj))</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">let obj = &#123;</span><br><span class="line">  a:1,</span><br><span class="line">  arr:[1,3,5,7,9],</span><br><span class="line">  c:&#123;</span><br><span class="line">    num:100</span><br><span class="line">  &#125;,</span><br><span class="line">  fn:function()&#123;</span><br><span class="line">     console.log(1)</span><br><span class="line">  &#125;,</span><br><span class="line">  date:new Date(),</span><br><span class="line">  reg:/\.*/g</span><br><span class="line">&#125;</span><br><span class="line">function clone1(obj)&#123; // 使用JSON.parse(JSON.stringify(obj))</span><br><span class="line">  return JSON.parse(JSON.stringify(obj))</span><br><span class="line">&#125;</span><br><span class="line">let obj1 = clone1(obj);</span><br><span class="line">console.log(obj === obj1); //false 代表复制成功了</span><br><span class="line">obj.c.num = 555;</span><br><span class="line"></span><br><span class="line">console.log(obj.c.num,obj1.c.num) // 555,100</span><br></pre></td></tr></table></figure><p>看起来是复制成功了！！~地址也变了，修改<code>obj</code>,<code>obj1</code>的引用地址不会跟着变化。</p><p>但是我们来<code>console</code>一下<code>obj</code>以及<code>obj1</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">console.log(obj)</span><br><span class="line">console.log(obj1)</span><br></pre></td></tr></table></figure><p><img src="https://imgkr.cn-bj.ufileos.com/5e000cff-e658-4162-a6d5-246ddb44d9a9.png" alt="打印结果"></p><p>似乎发现了离奇的事情，只有<code>obj.a</code>以及<code>obj.c</code>正确的复制了，<code>日期类型</code>、<code>方法</code>、<code>正则表达式</code>均没有复制成功，发生了一些奇怪的事情</p><h4 id="循环赋值-deepClone"><a href="#循环赋值-deepClone" class="headerlink" title="循环赋值 deepClone"></a>循环赋值 deepClone</h4><p>那么为了解决这种事情，就需要写一个<code>deepClone</code>方法来完成深复制了，参考了许多开源库的写法，将所有的复制项单独拆出，方便未来对特殊类型进行扩展，也防止不同功能间的变量互相干扰</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"> //既然是深复制，一定要传入一个object，再return 一个新的 Object</span><br><span class="line">function deepClone(obj)&#123;</span><br><span class="line">    let newObj;</span><br><span class="line">    if(obj instanceof Array)&#123; // 数组的话，要new一个数组</span><br><span class="line">      newObj = []</span><br><span class="line">    &#125;else if(obj instanceof Object)&#123;  // 对象的话，要new一个对象</span><br><span class="line">      newObj = &#123;&#125;</span><br><span class="line">    &#125;</span><br><span class="line">    if(obj === null) &#123;</span><br><span class="line">      return cloneNull(obj)</span><br><span class="line">    &#125;</span><br><span class="line">    if(typeof obj==&apos;function&apos;)&#123;</span><br><span class="line">        return cloneFunction(obj)</span><br><span class="line">    &#125;</span><br><span class="line">    if(typeof obj!=&apos;object&apos;) &#123;</span><br><span class="line">        return cloneOther(obj)</span><br><span class="line">    &#125;</span><br><span class="line">    if(obj instanceof RegExp) &#123;</span><br><span class="line">        return cloneRegExp(obj)</span><br><span class="line">    &#125;</span><br><span class="line">    if(obj instanceof Date)&#123;</span><br><span class="line">        return cloneDate(obj)</span><br><span class="line">    &#125;</span><br><span class="line">    if(obj instanceof Array)&#123;</span><br><span class="line">        for(let index in obj)&#123;</span><br><span class="line">            newObj[index] = deepClone(obj[index]); // 对数组子项进行复制</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    if(obj instanceof Object)&#123;</span><br><span class="line">        for(let key in obj)&#123;</span><br><span class="line">            newObj[key] = deepClone(obj[key]); // 对对象子项进行复制</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return newObj;</span><br><span class="line">&#125;</span><br><span class="line">function cloneNull(obj)&#123; // 复制NULL</span><br><span class="line">  return obj</span><br><span class="line">&#125;</span><br><span class="line">function cloneFunction(obj)&#123; // 复制方法，</span><br><span class="line">  //这个方法待完善，暂时未找到能够完美复制function的方案，如果有方案，望指出</span><br><span class="line">  return obj</span><br><span class="line">&#125;</span><br><span class="line">function cloneOther(obj)&#123; // 复制非对象的数据</span><br><span class="line">  return obj</span><br><span class="line">&#125;</span><br><span class="line">function cloneRegExp(obj)&#123; // 复制正则对象</span><br><span class="line">  return new RegExp(obj)</span><br><span class="line">&#125;</span><br><span class="line">function cloneDate(obj)&#123; // 复制日期对象</span><br><span class="line">  return new Date(obj)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这样一个基本上满足功能的深复制就完成了。先测试一下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">let obj = &#123;</span><br><span class="line">  a:1,</span><br><span class="line">  arr:[1,3,5,7,9],</span><br><span class="line">  c:&#123;</span><br><span class="line">    num:100</span><br><span class="line">  &#125;,</span><br><span class="line">  fn:function()&#123;</span><br><span class="line">     console.log(1)</span><br><span class="line">  &#125;,</span><br><span class="line">  date:new Date(),</span><br><span class="line">  reg:/\.*/g</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">let obj1 = deepClone(obj);</span><br><span class="line">console.log(obj.c === obj1.c); // false  代表复制成功</span><br><span class="line">console.log(obj.fn === obj1.fn);// true   由于方法单纯修改了引用的地址，所以这里是浅复制</span><br><span class="line">console.log(obj.date === obj1.date);// false  代表复制成功</span><br><span class="line">console.log(obj.reg === obj1.reg);// false  代表复制成功</span><br></pre></td></tr></table></figure><p>再<code>console</code>一下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">console.log(obj)</span><br><span class="line">console.log(obj1)</span><br></pre></td></tr></table></figure><p><img src="https://imgkr.cn-bj.ufileos.com/e74e8f1e-8a74-4990-a7f5-dac0681ca085.png" alt="打印结果"></p><p>这样，就完成了<code>deepClone</code>深复制方法</p><p>经过深复制后，图解如下<br><img src="https://imgkr.cn-bj.ufileos.com/4c9caffb-6cd8-4e89-b031-617f67097c66.jpg" alt="深复制后内存图解"></p><h4 id="优化-deepClone"><a href="#优化-deepClone" class="headerlink" title="优化 deepClone"></a>优化 deepClone</h4><p>上述代码还有优化空间，参考了<code>lodash</code>库，在进行 new 对象时，可以使用 <code>constructor</code>构造函数 来进行创建新的实例，这样</p><ol><li>可以不用判断递归中，是数组还是对象</li><li>如果深复制的某一项是某个原型的实例，深复制完成后，依然是该原型的实例</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line">function deepClone(obj)&#123;</span><br><span class="line">    let newObj = new obj.constructor;</span><br><span class="line">    if(obj === null) &#123;</span><br><span class="line">      return cloneNull(obj)</span><br><span class="line">    &#125;</span><br><span class="line">    if(typeof obj==&apos;function&apos;)&#123;</span><br><span class="line">        return cloneFunction(obj)</span><br><span class="line">    &#125;</span><br><span class="line">    if(typeof obj!=&apos;object&apos;) &#123;</span><br><span class="line">        return cloneOther(obj)</span><br><span class="line">    &#125;</span><br><span class="line">    if(obj instanceof RegExp) &#123;</span><br><span class="line">        return cloneRegExp(obj)</span><br><span class="line">    &#125;</span><br><span class="line">    if(obj instanceof Date)&#123;</span><br><span class="line">        return cloneDate(obj)</span><br><span class="line">    &#125;</span><br><span class="line">    if(obj instanceof Array)&#123;</span><br><span class="line">        for(let index in obj)&#123;</span><br><span class="line">            newObj[index] = deepClone(obj[index]); // 对数组子项进行复制</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    if(obj instanceof Object)&#123;</span><br><span class="line">        for(let key in obj)&#123;</span><br><span class="line">            newObj[key] = deepClone(obj[key]); // 对对象子项进行复制</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return newObj;</span><br><span class="line">&#125;</span><br><span class="line">function cloneNull(obj)&#123; // 复制NULL</span><br><span class="line">  return obj</span><br><span class="line">&#125;</span><br><span class="line">function cloneFunction(obj)&#123; // 复制方法，</span><br><span class="line">  //这个方法待完善，暂时未找到能够完美复制function的方案，如果有方案，望指出</span><br><span class="line">  return obj</span><br><span class="line">&#125;</span><br><span class="line">function cloneOther(obj)&#123; // 复制非对象的数据</span><br><span class="line">  return obj</span><br><span class="line">&#125;</span><br><span class="line">function cloneRegExp(obj)&#123; // 复制正则对象</span><br><span class="line">  return new RegExp(obj)</span><br><span class="line">&#125;</span><br><span class="line">function cloneDate(obj)&#123; // 复制日期对象</span><br><span class="line">  return new Date(obj)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="最终版本-deepClone"><a href="#最终版本-deepClone" class="headerlink" title="最终版本 deepClone"></a>最终版本 deepClone</h4><p>然后可以有一个合并版本的，比较节省代码，将下方区分开的复制方法，合并到<code>deepClone</code>中，可以极大地减少代码体积</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">function deepClone(obj)&#123; //</span><br><span class="line">    let newObj = new obj.constructor;</span><br><span class="line">    if(obj === null) return obj</span><br><span class="line">//  if(typeof obj==&apos;function&apos;) return obj</span><br><span class="line">//  由于typeof obj==&apos;function&apos;也符合下方的typeof obj!=&apos;object&apos;，所以此条可以省略</span><br><span class="line">    if(typeof obj!=&apos;object&apos;) return obj</span><br><span class="line">    if(obj instanceof RegExp) return new RegExp(obj)</span><br><span class="line">    if(obj instanceof Date) return new Date(obj)</span><br><span class="line">    // 运行到这里，基本上只存在数组和对象两种类型了</span><br><span class="line">    for(let index in obj)&#123;</span><br><span class="line">        newObj[index] = deepClone(obj[index]); // 对子项进行递归复制</span><br><span class="line">    &#125;</span><br><span class="line">    return newObj;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h2&gt;&lt;p&gt;在日常开发中，偶尔会遇到需要复制对象的情况，需要进行对象的复制。&lt;/p&gt;
&lt;p&gt;由于现在流行标题党，所以，一文带你了解js数据储存及深复制（
      
    
    </summary>
    
    
      <category term="javascript" scheme="http://www.meixiaohan.com/categories/javascript/"/>
    
    
      <category term="javascript" scheme="http://www.meixiaohan.com/tags/javascript/"/>
    
      <category term="js" scheme="http://www.meixiaohan.com/tags/js/"/>
    
      <category term="深拷贝" scheme="http://www.meixiaohan.com/tags/%E6%B7%B1%E6%8B%B7%E8%B4%9D/"/>
    
      <category term="deepClone" scheme="http://www.meixiaohan.com/tags/deepClone/"/>
    
  </entry>
  
  <entry>
    <title>撸一个简单的vue-router来剖析原理</title>
    <link href="http://www.meixiaohan.com/2020/03/10/Vue/vue-router-yuanli/"/>
    <id>http://www.meixiaohan.com/2020/03/10/Vue/vue-router-yuanli/</id>
    <published>2020-03-09T16:00:00.000Z</published>
    <updated>2020-03-09T08:50:49.360Z</updated>
    
    <content type="html"><![CDATA[<h1 id="理解"><a href="#理解" class="headerlink" title="理解"></a>理解</h1><p>随着前端业务的发展，<br>我们一般在写一个较为大型的<code>vue</code>项目时候，会使用到<code>vue-router</code>，来根据指定的<code>url</code>或者<code>hash</code>来进行内容的分发，可以达到不像服务端发送请求，就完成页面内容的切换，能够减少像服务器发送的请求，让用户进行页面跳转时候能够更快，体验更好</p><h1 id="疑问"><a href="#疑问" class="headerlink" title="疑问"></a>疑问</h1><p>在初学<code>vue-router</code>的时候，一般人都会有一个印象，<code>router-link</code>以及<code>router-view</code>都是<code>vue</code>原生自带的标签。但是这个印象是错误的，<code>vue-router</code>本质上是一个<code>vue</code>的插件，通过<code>Vue.use(VueRouter)</code>来使用这个插件。<code>router-link</code>以及<code>router-view</code>也是这个插件实现的自定义标签。</p><p>本文以开发插件的模式，撸一个<code>vue-router</code>插件以加深对其原理的了解</p><h1 id="url变化流程图解"><a href="#url变化流程图解" class="headerlink" title="url变化流程图解"></a>url变化流程图解</h1><p><img src="http://www.meixiaohan.com/file/myBlog/useFile/vue/img/vue-router-visio.jpg" alt="router流程图"></p><p>也就是说，要实现一个简单的<code>vue-router</code>，需要完成以下需求</p><h1 id="具体操作"><a href="#具体操作" class="headerlink" title="具体操作"></a>具体操作</h1><h2 id="创建vue项目"><a href="#创建vue项目" class="headerlink" title="创建vue项目"></a>创建vue项目</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vue create my-vue-router</span><br></pre></td></tr></table></figure><p>由于只着重于<code>vue-router</code>的内容，所以先使用原本的<code>vue-router</code>这样只替换<code>vue-router</code>源码文件即可</p><p>增加<code>vue-router</code><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vue add router</span><br></pre></td></tr></table></figure></p><p>然后项目目录就变成了<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">my-vue-router</span><br><span class="line">  |- node_modules</span><br><span class="line">  |- public</span><br><span class="line">  |- src</span><br><span class="line">      |- assets</span><br><span class="line">      |- components</span><br><span class="line">          |- HellowWorld.vue</span><br><span class="line">      |- router</span><br><span class="line">          |- index.js</span><br><span class="line">      |- views</span><br><span class="line">          |- About.vue</span><br><span class="line">          |- Home.vue</span><br><span class="line">      |- App.vue</span><br><span class="line">      |- main.js</span><br><span class="line">  |- .gitinore</span><br><span class="line">  |- babel.config.js</span><br><span class="line">  |- package.json</span><br><span class="line">  |- README.md</span><br><span class="line">  |- yarn.lock</span><br></pre></td></tr></table></figure></p><p>在目录中，新建一个<code>myRouter.js</code>的文件，来放置我们的源码</p><h2 id="新建自己的myRouter文件"><a href="#新建自己的myRouter文件" class="headerlink" title="新建自己的myRouter文件"></a>新建自己的myRouter文件</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">my-vue-router</span><br><span class="line">      |- node_modules</span><br><span class="line">      |- public</span><br><span class="line">      |- src</span><br><span class="line">          |- assets</span><br><span class="line">          |- components</span><br><span class="line">              |- HellowWorld.vue</span><br><span class="line">          |- router</span><br><span class="line">              |- index.js</span><br><span class="line">+             |- myRouter.js            </span><br><span class="line">          |- views</span><br><span class="line">              |- About.vue</span><br><span class="line">              |- Home.vue</span><br><span class="line">          |- App.vue</span><br><span class="line">          |- main.js</span><br><span class="line">      |- .gitinore</span><br><span class="line">      |- babel.config.js</span><br><span class="line">      |- package.json</span><br><span class="line">      |- README.md</span><br><span class="line">      |- yarn.lock</span><br></pre></td></tr></table></figure><h2 id="切换引入文件为自己写的myRouter-js"><a href="#切换引入文件为自己写的myRouter-js" class="headerlink" title="切换引入文件为自己写的myRouter.js"></a>切换引入文件为自己写的myRouter.js</h2><p>此时，<code>@/src/router/index.js</code>中的内容里，我们将导入的<code>vue-router</code>替换为我们的<code>myRouter.js</code><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">  import Vue from &apos;vue&apos;</span><br><span class="line">- import VueRouter from &apos;vue-router&apos;</span><br><span class="line">+ import VueRouter from &apos;./myRouter&apos;</span><br><span class="line">  import Home from &apos;../views/Home.vue&apos;</span><br><span class="line"></span><br><span class="line">  Vue.use(VueRouter)</span><br><span class="line"></span><br><span class="line">  const routes = [</span><br><span class="line">    &#123;</span><br><span class="line">      path: &apos;/&apos;,</span><br><span class="line">      name: &apos;Home&apos;,</span><br><span class="line">      component: Home</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      path: &apos;/about&apos;,</span><br><span class="line">      name: &apos;About&apos;,</span><br><span class="line">      // route level code-splitting</span><br><span class="line">      // this generates a separate chunk (about.[hash].js) for this route</span><br><span class="line">      // which is lazy-loaded when the route is visited.</span><br><span class="line">      component: () =&gt; import(/* webpackChunkName: &quot;about&quot; */ &apos;../views/About.vue&apos;)</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line"></span><br><span class="line">  const router = new VueRouter(&#123;</span><br><span class="line">    mode: &apos;history&apos;,</span><br><span class="line">    base: process.env.BASE_URL,</span><br><span class="line">    routes</span><br><span class="line">  &#125;)</span><br><span class="line"></span><br><span class="line">  export default router</span><br></pre></td></tr></table></figure></p><p>这里我们可以看到，代码执行的流程为<br>引入<code>myRouter.js</code>-&gt;<code>配置routes对象</code>-&gt;<code>new VueRouter</code>-&gt;<code>export default</code>导出</p><p>此处用到了 <code>Vue.use()</code>这个<code>API</code></p><h2 id="Vue-use"><a href="#Vue-use" class="headerlink" title="Vue.use()"></a>Vue.use()</h2><p><code>vue</code>中的插件，一个核心的<code>api</code>就是<code>vue.use()</code></p><blockquote><p>安装 Vue.js 插件。如果插件是一个对象，必须提供 install 方法。如果插件是一个函数，它会被作为install 方法。install 方法调用时，会将 Vue 作为参数传入。<br>该方法需要在调用 new Vue() 之前被调用。<br>当 install 方法被同一个插件多次调用，插件将只会被安装一次。</p></blockquote><p>也就是说，我们在自己造的<code>myRouter</code>里得实现这个<code>install</code>方法</p><h1 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h1><ol><li>提供一个构造类，能够使用<code>new VueRouter</code>来生成实例</li><li>实现install方法</li><li>监听<code>url</code>变化，并双向绑定current方法</li><li>注册自定义组件<code>router-link</code>与<code>router-view</code></li><li>实现用户配置的路由数组到map的转换,方便快速的查询到路由匹配的对象</li></ol><h1 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h1><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><span class="line">let Vue;//由于使用者肯定是使用vue.use引入的这个插件，所以代码里就不引入vue.js了，防止重复打包</span><br><span class="line">// 需求1 声明一个拥有constructor构造器的class</span><br><span class="line">class VueRouter&#123;</span><br><span class="line">    constructor(options=&#123;&#125;)&#123;// 构造函数</span><br><span class="line">        this.$options=options;// 保存配置项</span><br><span class="line">        this.app = &#123; // 声明一个拥有current的变量，已完成路由的双向绑定</span><br><span class="line">            current:&quot;/&quot;</span><br><span class="line">        &#125;</span><br><span class="line">        Vue.util.defineReactive(this.app,&apos;current&apos;,this.app.current);//vue的拦截方法，会该值增加get拦截以收集依赖，set拦截以触发双向绑定</span><br><span class="line">        this.routerMap=&#123;&#125;; // 创建key-value模式的routerMap，便于使用key能够快速的找到即将render(渲染)的组件</span><br><span class="line">        this.init(options); // 执行init方法，以完成需求3,4,5</span><br><span class="line">    &#125;</span><br><span class="line">    init(options=&#123;&#125;)&#123;</span><br><span class="line">        this.bindBrowserEvents()// 绑定浏览器事件</span><br><span class="line">        this.initComponent()//注册router-view及router-link组件</span><br><span class="line">        this.createRouterMap(options.routes)//创建key-value模式的routerMap</span><br><span class="line">    &#125;</span><br><span class="line">    createRouterMap(arr=[])&#123; // 创建routerMap</span><br><span class="line">        arr.forEach(item =&gt; &#123;</span><br><span class="line">            this.routerMap[item.path]=item</span><br><span class="line">        &#125;);</span><br><span class="line">        //  处理完后routerMap格式如下</span><br><span class="line">        //  this.routerMap = &#123;</span><br><span class="line">        //    &apos;/&apos;:&#123;</span><br><span class="line">        //      path: &apos;/&apos;,</span><br><span class="line">        //      name: &apos;Home&apos;,</span><br><span class="line">        //      component: Home</span><br><span class="line">        //    &#125;,</span><br><span class="line">        //    &apos;/about&apos;:&#123;</span><br><span class="line">        //      path: &apos;/about&apos;,</span><br><span class="line">        //      name: &apos;About&apos;,</span><br><span class="line">        //      component: () =&gt; import(/* webpackChunkName: &quot;about&quot; */ &apos;../views/About.vue&apos;)</span><br><span class="line">        //    &#125;</span><br><span class="line">        //  &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    bindBrowserEvents()&#123; // hash模式监听 hashchange 方法</span><br><span class="line">        window.addEventListener(&apos;load&apos;,this.onHashChange.bind(this))</span><br><span class="line">        window.addEventListener(&apos;hashchange&apos;,this.onHashChange.bind(this))</span><br><span class="line">    &#125;</span><br><span class="line">    initComponent()&#123; // 注册自定义组件RouterLink及RouterView</span><br><span class="line">        Vue.component(&apos;RouterLink&apos;,&#123;</span><br><span class="line">            props: &#123;</span><br><span class="line">                to: String</span><br><span class="line">            &#125;,</span><br><span class="line">            render(h) &#123;</span><br><span class="line">                return h(&apos;a&apos;,&#123;</span><br><span class="line">                    attrs:&#123;</span><br><span class="line">                        href:&apos;#&apos;+this.to</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;,this.$slots.default)</span><br><span class="line">            &#125;,</span><br><span class="line">        &#125;)</span><br><span class="line">        Vue.component(&apos;RouterView&apos;,&#123;</span><br><span class="line">            render:(h)=&gt;&#123;</span><br><span class="line">                const component = this.routerMap[this.app.current].component</span><br><span class="line">                return h(component)</span><br><span class="line">            &#125;,</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    onHashChange()&#123; // hash变化时，改变 this.app.current </span><br><span class="line">        window.location.hash = window.location.hash || &apos;/&apos;; // 如果hash没有值，则默认给补一个/#/</span><br><span class="line">        if(this.routerMap[window.location.hash.slice(1)])&#123; // this.app.current = hash值</span><br><span class="line">            this.app.current = window.location.hash.slice(1);</span><br><span class="line">        &#125;else&#123;</span><br><span class="line">            this.app.current = &apos;/&apos;;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        // 此处执行完后，则由于双向绑定，会触发routerView进行重新渲染</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// 需求2 实现install方法</span><br><span class="line">VueRouter.install = function(_Vue)&#123;</span><br><span class="line">  Vue = _Vue; // 因为一定会先走install，所以将这个传入的Vue实例，保存到变量Vue中</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>注释都写在代码里啦，可以执行简单的路由双向绑定功能，有哪里有疑问可以提出~互相学习~</p><p>觉得好的话，可以给我的 <a href="https://github.com/mr-xiao-han/myBlog" target="_blank" rel="noopener">github</a>点个<code>star</code>哦</p><iframe style="margin-left: 2px; margin-bottom:-5px;" frameborder="0" scrolling="0" width="100px" height="20px" src="https://ghbtns.com/github-btn.html?user=mr-xiao-han&repo=myBlog&type=star&count=true"><br></iframe>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;理解&quot;&gt;&lt;a href=&quot;#理解&quot; class=&quot;headerlink&quot; title=&quot;理解&quot;&gt;&lt;/a&gt;理解&lt;/h1&gt;&lt;p&gt;随着前端业务的发展，&lt;br&gt;我们一般在写一个较为大型的&lt;code&gt;vue&lt;/code&gt;项目时候，会使用到&lt;code&gt;vue-router&lt;/
      
    
    </summary>
    
    
      <category term="vue" scheme="http://www.meixiaohan.com/categories/vue/"/>
    
    
      <category term="vue" scheme="http://www.meixiaohan.com/tags/vue/"/>
    
      <category term="路由" scheme="http://www.meixiaohan.com/tags/%E8%B7%AF%E7%94%B1/"/>
    
      <category term="vue-router" scheme="http://www.meixiaohan.com/tags/vue-router/"/>
    
  </entry>
  
  <entry>
    <title>vue-组件化-插槽(slot)</title>
    <link href="http://www.meixiaohan.com/2020/03/03/Vue/vue-component-slot/"/>
    <id>http://www.meixiaohan.com/2020/03/03/Vue/vue-component-slot/</id>
    <published>2020-03-02T16:00:00.000Z</published>
    <updated>2020-03-03T11:42:37.364Z</updated>
    
    <content type="html"><![CDATA[<h1 id="理解"><a href="#理解" class="headerlink" title="理解"></a>理解</h1><p>Vue组件化中，当我们在设计一个组件的时候，可能会保留一部分，让使用者自定义的内容，比如：</p><ol><li>导航栏组件中，右上角的分享按钮，左上角做菜单按钮</li><li>弹出框组件中，弹出框的提示内容等</li><li>…</li></ol><p>在这种场景下，把保留给使用者的部分，叫做插槽(slot)</p><h1 id="插槽分类"><a href="#插槽分类" class="headerlink" title="插槽分类"></a>插槽分类</h1><h2 id="匿名插槽"><a href="#匿名插槽" class="headerlink" title="匿名插槽"></a>匿名插槽</h2><p>理解：</p><ol><li>所谓匿名插槽，就是这个插槽里，没有声明任何名称，使用者放进来的东西，都扔进这个插槽中。</li><li>匿名插槽是一种特殊的具名插槽，也就是名为<code>default</code>的插槽</li></ol><p>写法：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">//自定义组件中</span><br><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        &lt;slot&gt;&lt;slot&gt;//匿名插槽</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">//页面(使用者)使用</span><br><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        &lt;myComponent&gt;&lt;p&gt;我被放进了插槽中&lt;/p&gt;&lt;/myComponent&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure></p><p>代码中<code>我被放进了插槽中</code>这句话，就进入了自定义组件的匿名插槽中，从而变成了<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">//自定义组件中</span><br><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        &lt;div&gt;</span><br><span class="line">            &lt;p&gt;我被放进了插槽中&lt;/p&gt;&lt;!-- 匿名插槽中放入了内容 --&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure></p><h2 id="具名插槽"><a href="#具名插槽" class="headerlink" title="具名插槽"></a>具名插槽</h2><p>理解：所谓具名插槽，就是这个插槽里，这个插槽被命了名，使用者放进来的东西，声明了插槽的名称，会被分发进这个具名插槽中。<br>写法：使用<code>template</code>标签声明<code>具名插槽</code>名称<code>&lt;template v-slot:插槽名&gt;&lt;/template&gt;</code><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">//自定义组件中</span><br><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        &lt;div class=&apos;slot1&apos;&gt;</span><br><span class="line">            &lt;slot name=&apos;slot1&apos;&gt;&lt;slot&gt;&lt;!-- 名为“slot1”的具名插槽 --&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">        &lt;div class=&apos;slot2&apos;&gt;</span><br><span class="line">            &lt;slot name=&apos;slot2&apos;&gt;&lt;slot&gt;&lt;!-- 名为“slot2”的具名插槽 --&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">        &lt;slot&gt;&lt;slot&gt;//这里是个匿名插槽</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">//页面(使用者)使用</span><br><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        &lt;myComponent&gt;</span><br><span class="line">            &lt;template v-slot:slot1&gt;</span><br><span class="line">                &lt;p&gt;名为slot1的具名插槽中&lt;/p&gt;</span><br><span class="line">            &lt;/template&gt;</span><br><span class="line">            &lt;a&gt;啦啦啦啦德玛西亚&lt;/a&gt;</span><br><span class="line">            &lt;template v-slot:slot2&gt;</span><br><span class="line">                &lt;p&gt;名为slot2的具名插槽中&lt;/p&gt;</span><br><span class="line">            &lt;/template&gt;</span><br><span class="line">            &lt;p&gt;啦啦啦啦德玛西亚&lt;/p&gt;</span><br><span class="line">        &lt;/myComponent&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure></p><p>代码被分发到对应插槽后的内容<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">//自定义组件中</span><br><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        &lt;div class=&apos;slot1&apos;&gt;</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &lt;p&gt;名为slot1的具名插槽中&lt;/p&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">        &lt;div class=&apos;slot2&apos;&gt;</span><br><span class="line">            &lt;div&gt;</span><br><span class="line">                &lt;p&gt;名为slot2的具名插槽中&lt;/p&gt;</span><br><span class="line">            &lt;/div&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">        &lt;div&gt;</span><br><span class="line">            &lt;a&gt;啦啦啦啦德玛西亚&lt;/a&gt;</span><br><span class="line">            &lt;p&gt;啦啦啦啦德玛西亚&lt;/p&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure></p><h2 id="作用域插槽"><a href="#作用域插槽" class="headerlink" title="作用域插槽"></a>作用域插槽</h2><p>理解：一种能够将子组件可用的内容暴露给父组件的插槽。<br>比如：我们有的时候，需要一些子组件里的东西，做内容拼接，就像一个用户名输入框，我们希望所有的用户名，都跟随一个<code>user_</code>的前缀，此处就可以使用到作用域插槽<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">//自定义组件中</span><br><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        &lt;slot :user=&apos;username&apos;&gt;&lt;slot&gt;//匿名插槽</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">    export default &#123;</span><br><span class="line">        data()&#123;</span><br><span class="line">            return &#123;</span><br><span class="line">                username:&#123;</span><br><span class="line">                    prefix:&quot;user_&quot;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line"></span><br><span class="line">//页面(使用者)使用</span><br><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        &lt;myComponent v-slot=&apos;obj&apos;&gt;</span><br><span class="line">            &#123;&#123;obj.user.prefix&#125;&#125;小寒大人</span><br><span class="line">        &lt;/myComponent&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure></p><p>编译后的结果就变成了<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        &lt;div&gt;</span><br><span class="line">            user_小寒大人</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure></p><h1 id="默认值-后备内容"><a href="#默认值-后备内容" class="headerlink" title="默认值(后备内容)"></a>默认值(后备内容)</h1><h2 id="理解-1"><a href="#理解-1" class="headerlink" title="理解"></a>理解</h2><p>插槽是拥有默认值功能的，如果对应的slot没有传入内容，则会使用slot的默认值</p><h2 id="写法"><a href="#写法" class="headerlink" title="写法"></a>写法</h2><p>以匿名参数为例<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">//自定义组件中</span><br><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        &lt;slot&gt;&lt;p&gt;这里是默认的内容&lt;/p&gt;&lt;/slot&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">//页面(使用者)使用</span><br><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        &lt;myComponent&gt;&lt;/myComponent&gt;</span><br><span class="line">        &lt;myComponent&gt;替换了&lt;/myComponent&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure></p><p>最终表现结果为<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">    &lt;div&gt;</span><br><span class="line">        &lt;div&gt;</span><br><span class="line">            &lt;p&gt;这里是默认的内容&lt;/p&gt;</span><br><span class="line">        &lt;/div&gt;  </span><br><span class="line">        &lt;div&gt;</span><br><span class="line">            替换了</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure></p><h1 id="动态插槽名"><a href="#动态插槽名" class="headerlink" title="动态插槽名"></a>动态插槽名</h1><h2 id="理解-2"><a href="#理解-2" class="headerlink" title="理解"></a>理解</h2><p>可以使用动态值来定某些内容进入某些具名插槽中</p><h2 id="写法-1"><a href="#写法-1" class="headerlink" title="写法"></a>写法</h2><p>正常的具名插槽为<code>v-slot:插槽名</code>，动态的写法为<code>v-slot:[dynamicSlotName]</code>，此写法仅在<code>vue2.6.0后的vue中版本使用</code></p><h1 id="简写插槽名"><a href="#简写插槽名" class="headerlink" title="简写插槽名"></a>简写插槽名</h1><p>正常的具名插槽为<code>v-slot:插槽名</code>，简写的写法为<code>#插槽名</code>，此写法仅在<code>vue2.6.0后vue中版本使用</code></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;理解&quot;&gt;&lt;a href=&quot;#理解&quot; class=&quot;headerlink&quot; title=&quot;理解&quot;&gt;&lt;/a&gt;理解&lt;/h1&gt;&lt;p&gt;Vue组件化中，当我们在设计一个组件的时候，可能会保留一部分，让使用者自定义的内容，比如：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;导航栏组件中，右上角的
      
    
    </summary>
    
    
      <category term="vue" scheme="http://www.meixiaohan.com/categories/vue/"/>
    
    
      <category term="vue" scheme="http://www.meixiaohan.com/tags/vue/"/>
    
      <category term="组件化" scheme="http://www.meixiaohan.com/tags/%E7%BB%84%E4%BB%B6%E5%8C%96/"/>
    
      <category term="插槽" scheme="http://www.meixiaohan.com/tags/%E6%8F%92%E6%A7%BD/"/>
    
  </entry>
  
  <entry>
    <title>从0开始探究vue-组件化-组件之间传值</title>
    <link href="http://www.meixiaohan.com/2020/02/28/Vue/vue-component/"/>
    <id>http://www.meixiaohan.com/2020/02/28/Vue/vue-component/</id>
    <published>2020-02-27T16:00:00.000Z</published>
    <updated>2020-03-04T14:19:10.978Z</updated>
    
    <content type="html"><![CDATA[<h1 id="理解"><a href="#理解" class="headerlink" title="理解"></a>理解</h1><p>Vue中有个非常重要的核心思想，就是组件化，组件化是为了代码复用</p><h1 id="什么是组件化"><a href="#什么是组件化" class="headerlink" title="什么是组件化"></a>什么是组件化</h1><p>组件化，就像一个电脑主机里的主板，有内存条的插口，有硬盘，光驱等等的插口，我们的项目，就像一个电脑主机，通过各种组件化的模块（硬盘、内存等），来拼合成一个完整的电脑。<br><img src="http://www.meixiaohan.com/file/myBlog/useFile/vue/img/components.png" alt="vue组件化"></p><p>（图片来源 <a href="https://cn.vuejs.org/v2/guide/#%E7%BB%84%E4%BB%B6%E5%8C%96%E5%BA%94%E7%94%A8%E6%9E%84%E5%BB%BA" target="_blank" rel="noopener">vue-组件化应用构建</a>）</p><p>如图，每一个块都是一个组件，由许许多多的组件拼合而成，可以无限的嵌套下去</p><h1 id="组件化的好处"><a href="#组件化的好处" class="headerlink" title="组件化的好处"></a>组件化的好处</h1><ol><li>模块复用，提高效率，让重复的代码只写一遍。</li><li>预留个性化设置，可以保证模块，既通用，又可变。</li><li>提高可维护性，如果一个项目多个页面使用了同一个组件（例如消息弹框），如果修改弹框样式，只需要修改这个模块即可。</li></ol><h1 id="写法"><a href="#写法" class="headerlink" title="写法"></a>写法</h1><h2 id="cli模式"><a href="#cli模式" class="headerlink" title="cli模式"></a>cli模式</h2><p>组件部分<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;&lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">export default &#123;</span><br><span class="line">    name:&quot;myAlert&quot;</span><br><span class="line">&#125;;</span><br><span class="line">&lt;style&gt;&lt;/style&gt;</span><br></pre></td></tr></table></figure></p><p>使用者部分<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;myAlert&gt;&lt;/myAlert&gt; &lt;!-- 实例中使用组件 --&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script&gt;</span><br><span class="line">import myAlert from &apos;@/components/alert.vue&apos;;//导入自己写的组件</span><br><span class="line">export default &#123;</span><br><span class="line">  components:&#123;myAlert&#125;//在这个vue实例中注册组件</span><br><span class="line">&#125;;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">&lt;style&gt;&lt;/style&gt;</span><br></pre></td></tr></table></figure></p><h2 id="引入vue-js模式"><a href="#引入vue-js模式" class="headerlink" title="引入vue.js模式"></a>引入vue.js模式</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">// 定义名为 todo-item 的新组件</span><br><span class="line">Vue.component(&apos;myAlert&apos;, &#123;</span><br><span class="line">  template: &apos;&lt;div&gt;这是一个弹框&lt;/div&gt;&apos;</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">var app = new Vue(...)</span><br></pre></td></tr></table></figure><p>html部分使用<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;div&gt;</span><br><span class="line">    &lt;myAlert&gt;&lt;/myAlert&gt;</span><br><span class="line">&lt;/div&gt;</span><br></pre></td></tr></table></figure></p><h1 id="组件传值"><a href="#组件传值" class="headerlink" title="组件传值"></a>组件传值</h1><p><code>Vue</code>中存在的组件之间传值的方案如下</p><h2 id="父-gt-子"><a href="#父-gt-子" class="headerlink" title="父=&gt;子"></a>父=&gt;子</h2><h3 id="props"><a href="#props" class="headerlink" title="props"></a>props</h3><p>子组件中声明<code>props</code>,父组件往对应的<code>props值中传递</code></p><h3 id="refs"><a href="#refs" class="headerlink" title="$refs"></a>$refs</h3><p>父组件使用<code>this.$refs.组件名.变量</code>来选中子组件并修改子组件的内容</p><h3 id="children"><a href="#children" class="headerlink" title="$children"></a>$children</h3><p>父组件使用<code>this.$children[0].变量</code>来选中并修改子组件的内容</p><p>需要注意的是：由<a href="https://cn.vuejs.org/v2/api/#vm-children" target="_blank" rel="noopener">官网vm.$children</a>得知</p><blockquote><p>$children 并不保证顺序，也不是响应式的 </p></blockquote><p>所以一般不建议使用此方法来进行传值，因为不能很稳定的找到指定组件的实例，除非这个页面只有一个子组件</p><p>另外，此例中，<code>this.$children[0]</code>不是响应式的<code>this.$children[0].变量</code>是响应式的。</p><h2 id="子-gt-父"><a href="#子-gt-父" class="headerlink" title="子=&gt;父"></a>子=&gt;父</h2><h3 id="emit"><a href="#emit" class="headerlink" title="$emit"></a>$emit</h3><p>此处为<code>观察者模式</code></p><ol><li>子组件调用<code>this.$emit(&#39;confirm&#39;,&#39;点击了确定&#39;)</code>来派发<code>confirm</code>事件</li><li>父组件中<code>&lt;myAlert @confirm=&#39;successCallback&#39;&gt;&lt;/myAlert&gt;</code>来监听事件;<br>注意：此处为，谁派发就是谁监听，也就是说，<code>confirm</code>事件的派发者和监听者，都是<code>myAlert</code>组件，<code>myAlert</code>组件监听完毕后将调用父组件的<code>successCallback</code>回调事件，当然这个<code>监听的事件名</code>和<code>触发的事件名</code>都是<code>可以自定义</code>的。</li></ol><h2 id="兄弟组件之间互相传值"><a href="#兄弟组件之间互相传值" class="headerlink" title="兄弟组件之间互相传值"></a>兄弟组件之间互相传值</h2><h3 id="使用公共节点搭桥"><a href="#使用公共节点搭桥" class="headerlink" title="使用公共节点搭桥"></a>使用公共节点搭桥</h3><ol><li><p>使用公共父级组件<code>$parents</code>或者<code>$root</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">//组件一</span><br><span class="line">this.$parents.$on(&apos;foo&apos;,(e)=&gt;&#123;</span><br><span class="line">    console.log(e);//此处e为$emit时传入的值</span><br><span class="line">&#125;)</span><br><span class="line">//组件二</span><br><span class="line">this.$parents.$emit(&apos;foo&apos;,&apos;bar&apos;);//控制台输出bar</span><br></pre></td></tr></table></figure></li><li><p>使用任意两个组件之间传值的方案 <a href="#evert-components">点击查看</a></p></li></ol><h2 id="跨辈分传值"><a href="#跨辈分传值" class="headerlink" title="跨辈分传值"></a>跨辈分传值</h2><p>概念，所谓跨辈分传值，就是</p><p>祖辈-&gt;父辈-&gt;子辈-&gt;孙辈-&gt;…<br>其中，垮了一个辈分或多个辈分的就是跨辈分传值，例如，祖辈及孙辈</p><h3 id="provide-inject"><a href="#provide-inject" class="headerlink" title="provide/inject"></a>provide/inject</h3><p>由于多级嵌套，使用<code>props</code>传递显然是不现实的</p><p>针对这种情况，<code>vue</code>提供了 <code>provide/inject</code>两个<code>API</code>来完成这件事</p><ol><li>祖辈使用<code>provide</code>声明一个变量</li><li>孙辈使用<code>inject</code>来注入祖辈声明的变量</li></ol><p>写法：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">//祖辈</span><br><span class="line">export default &#123;</span><br><span class="line">    provide()&#123;//此处可以传入动态变量，与data类似</span><br><span class="line">        return &#123;</span><br><span class="line">            componentYeye:this</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    data()&#123;</span><br><span class="line">        return &#123;</span><br><span class="line">            yeyedeBianliang:&apos;爷爷的变量&apos;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">//孙辈</span><br><span class="line">export default &#123;</span><br><span class="line">    inject:[&apos;componentYeye&apos;],//此处为数组，注入祖辈声明的变量</span><br><span class="line">    mounted()&#123;</span><br><span class="line">        console.log(this.componentYeye.yeyedeBianliang);//爷爷的变量</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>注意</p><ol><li>此方法多用来制作组件库时使用。</li><li>此方法不建议直接在孙辈修改祖辈的数据。因为这些数据可能在多个子组件中使用，如果要修改，应该调用祖辈组件变量的方法来修改，与<code>vuex</code>中建议变量修改都是用<code>commit</code>类似</li></ol><h3 id="使用任意两个组件之间传值的方案-点击查看"><a href="#使用任意两个组件之间传值的方案-点击查看" class="headerlink" title="使用任意两个组件之间传值的方案 点击查看"></a>使用任意两个组件之间传值的方案 <a href="#evert-components">点击查看</a></h3><h2 id="任意两个组件之间传值"><a href="#任意两个组件之间传值" class="headerlink" title="任意两个组件之间传值"></a>任意两个组件之间传值</h2><p><a id="evert-components"></a></p><h3 id="原型挂载"><a href="#原型挂载" class="headerlink" title="原型挂载"></a>原型挂载</h3><p>所谓原型挂载，就是在<code>main.js</code>中将公共变量，事件，都挂在到Vue原型上<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">//main.js</span><br><span class="line">Vue.prototype.$globalData = &#123;&#125;</span><br><span class="line">Vue.prototype.$sayName = function(e)&#123;</span><br><span class="line">    console.log(&apos;我的名字是&apos;,e)</span><br><span class="line">&#125;</span><br><span class="line">new Vue(&#123;...&#125;)</span><br><span class="line"></span><br><span class="line">//组件一</span><br><span class="line">Vue.prototype.$globalData.name=&apos;小明&apos;;</span><br><span class="line">this.$sayName(&apos;小王&apos;);//我的名字是小王</span><br><span class="line"></span><br><span class="line">//组件二</span><br><span class="line">console.log(this.$sayName.name);//小明</span><br><span class="line">this.$sayName(&apos;小王&apos;);//我的名字是小王</span><br></pre></td></tr></table></figure></p><h3 id="事件总线"><a href="#事件总线" class="headerlink" title="事件总线"></a>事件总线</h3><p>所谓事件总线，就是在当前的<code>Vue</code>实例之外，再创建一个Vue实例来专门进行变量传递，事件处理，管理回调事件等<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">//main.js中</span><br><span class="line">Vue.prototype.$bus = new Vue();</span><br><span class="line">new Vue(&#123;...&#125;)</span><br><span class="line"></span><br><span class="line">//组件一</span><br><span class="line">this.$bus.$on(&apos;sayName&apos;,(e)=&gt;&#123;</span><br><span class="line">    console.log(&apos;我的名字是&apos;,e)</span><br><span class="line">&#125;)</span><br><span class="line">//组件二</span><br><span class="line">this.$bus.$emit(&apos;sayName&apos;,&apos;小明&apos;);//我的名字是 小明</span><br></pre></td></tr></table></figure></p><h3 id="vuex"><a href="#vuex" class="headerlink" title="vuex"></a>vuex</h3><p><code>Vuex</code>是<code>Vue</code>提供的一种，专门用来管理<code>vue</code>中的公共状态，事件等等。详见 <a href="http://www.meixiaohan.com/2020/02/26/Vue/vuex/">从0开始探究vue-公共变量的管理</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;理解&quot;&gt;&lt;a href=&quot;#理解&quot; class=&quot;headerlink&quot; title=&quot;理解&quot;&gt;&lt;/a&gt;理解&lt;/h1&gt;&lt;p&gt;Vue中有个非常重要的核心思想，就是组件化，组件化是为了代码复用&lt;/p&gt;
&lt;h1 id=&quot;什么是组件化&quot;&gt;&lt;a href=&quot;#什么是组件化&quot;
      
    
    </summary>
    
    
      <category term="vue" scheme="http://www.meixiaohan.com/categories/vue/"/>
    
    
      <category term="vue" scheme="http://www.meixiaohan.com/tags/vue/"/>
    
      <category term="组件化" scheme="http://www.meixiaohan.com/tags/%E7%BB%84%E4%BB%B6%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>从0开始探究vue-公共变量的管理</title>
    <link href="http://www.meixiaohan.com/2020/02/26/Vue/vuex/"/>
    <id>http://www.meixiaohan.com/2020/02/26/Vue/vuex/</id>
    <published>2020-02-25T16:00:00.000Z</published>
    <updated>2020-03-01T07:09:06.555Z</updated>
    
    <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>在<code>Vue</code>项目中，我们总会遇到一些公共数据的处理，如方法拦截，全局变量等，本文旨在解决这些问题</p><h1 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h1><h2 id="事件总线"><a href="#事件总线" class="headerlink" title="事件总线"></a>事件总线</h2><p>所谓事件总线，就是在当前的<code>Vue</code>实例之外，再创建一个Vue实例来专门进行变量传递，事件处理，管理回调事件等<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">//main.js中</span><br><span class="line">Vue.prototype.$bus = new Vue();</span><br><span class="line">new Vue(&#123;...&#125;)</span><br><span class="line"></span><br><span class="line">//页面一</span><br><span class="line">this.$bus.$on(&apos;sayName&apos;,(e)=&gt;&#123;</span><br><span class="line">    alert(&apos;我的名字是&apos;,e)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">//页面二</span><br><span class="line">this.$bus.$emit(&apos;sayName&apos;,&apos;小明&apos;);//我的名字是 小明</span><br></pre></td></tr></table></figure></p><h2 id="原型挂载"><a href="#原型挂载" class="headerlink" title="原型挂载"></a>原型挂载</h2><p>所谓原型挂载，就是在<code>main.js</code>中将公共变量，事件，都挂在到Vue原型上<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">//main.js</span><br><span class="line">Vue.prototype.$globalData = &#123;&#125;</span><br><span class="line">Vue.prototype.$sayName = function(e)&#123;</span><br><span class="line">    console.log(&apos;我的名字是&apos;,e)</span><br><span class="line">&#125;</span><br><span class="line">new Vue(&#123;...&#125;)</span><br><span class="line"></span><br><span class="line">//组件一</span><br><span class="line">Vue.prototype.$globalData.name=&apos;小明&apos;;</span><br><span class="line">this.$sayName(&apos;小王&apos;);//我的名字是小王</span><br><span class="line"></span><br><span class="line">//组件二</span><br><span class="line">console.log(this.$sayName.name);//小明</span><br><span class="line">this.$sayName(&apos;小王&apos;);//我的名字是小王</span><br></pre></td></tr></table></figure></p><h2 id="vuex"><a href="#vuex" class="headerlink" title="vuex"></a>vuex</h2><p><code>Vuex</code>是<code>Vue</code>提供的一种，专门用来管理<code>vue</code>中的公共状态，事件等等，以应用登录为例</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line">//新建store.js</span><br><span class="line">import Vue from &apos;vue&apos;</span><br><span class="line">import Vuex from &apos;vuex&apos;</span><br><span class="line">import axios from &apos;axios&apos;</span><br><span class="line">Vue.use(Vuex)</span><br><span class="line">export default new Vuex.Store(&#123;</span><br><span class="line">  state: &#123;//此处为公共变量</span><br><span class="line">    userId:&quot;&quot;,//用户Id</span><br><span class="line">    loginSession:&quot;&quot;//用户登录凭证</span><br><span class="line">  &#125;,</span><br><span class="line">  mutations: &#123;//此处为同步方法</span><br><span class="line">    setLoginSession(state,loginSession)&#123;//存入state中的用户凭证</span><br><span class="line">        state.loginSession = loginSession;</span><br><span class="line">    &#125;,</span><br><span class="line">    setUserId(state,loginSession)&#123;//存入state中的用户凭证</span><br><span class="line">        state.loginSession = &apos;user_&apos;+Math.floor(Math.random()*100000000000);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  actions: &#123;//此处为异步方法</span><br><span class="line">    getUserId(&#123;state,commit&#125;,options=&#123;&#125;)&#123;//从服务器取登录凭证，然后返回是否登录状态</span><br><span class="line">        return new Proise((resolve)=&gt;&#123;//返回一个promise对象，来让调用者可以使用.then来进行下一步操作</span><br><span class="line">            axios.get(&apos;api&apos;).then((res)=&gt;&#123;</span><br><span class="line">                commit(&apos;setLoginSession&apos;,res.data.loginSession)</span><br><span class="line">                resolve(this.getters.isLogin)</span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;))</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  modules: &#123;//此处为混入更多的vuex小模块</span><br><span class="line">    </span><br><span class="line">  &#125;,</span><br><span class="line">  gatters: &#123;//此处为计算变量</span><br><span class="line">      isLogin()&#123;</span><br><span class="line">          return (this.userId&amp;&amp;this.loginSession)?true:false</span><br><span class="line">      &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br><span class="line">//main.js中注入vuex</span><br><span class="line">import store from &apos;./store/store.js&apos;</span><br><span class="line">Vue.prototype.$store = store;</span><br><span class="line"></span><br><span class="line">//app.vue中</span><br><span class="line">export default &#123;</span><br><span class="line">    data()&#123;</span><br><span class="line">        return &#123;&#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    mounted()&#123;</span><br><span class="line">        this.$store.commit(&apos;setUserId&apos;);//设置用户Id</span><br><span class="line">        this.$store.dispatch(&apos;getUserId&apos;).then((result)=&gt;&#123;//查询登录凭证，并返回登录结果</span><br><span class="line">            console.log(this.$store.getters.isLogin,result);//true  true  此处也可以查看计算属性中的是否登录状态</span><br><span class="line">            if(result)&#123;</span><br><span class="line">                alert(&apos;登录了&apos;)</span><br><span class="line">            &#125;else&#123;</span><br><span class="line">                alert(&apos;未登录&apos;)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;在&lt;code&gt;Vue&lt;/code&gt;项目中，我们总会遇到一些公共数据的处理，如方法拦截，全局变量等，本文旨在解决这些问题&lt;/p&gt;
&lt;h1 id
      
    
    </summary>
    
    
      <category term="vue" scheme="http://www.meixiaohan.com/categories/vue/"/>
    
    
      <category term="vue" scheme="http://www.meixiaohan.com/tags/vue/"/>
    
      <category term="vuex" scheme="http://www.meixiaohan.com/tags/vuex/"/>
    
  </entry>
  
  <entry>
    <title>从0开始探究vue-双向绑定原理</title>
    <link href="http://www.meixiaohan.com/2020/02/20/Vue/vue-mvvm-yuanli/"/>
    <id>http://www.meixiaohan.com/2020/02/20/Vue/vue-mvvm-yuanli/</id>
    <published>2020-02-19T16:00:00.000Z</published>
    <updated>2020-02-28T02:18:26.437Z</updated>
    
    <content type="html"><![CDATA[<h1 id="理解"><a href="#理解" class="headerlink" title="理解"></a>理解</h1><p>vue是一个非常优秀的框架，其优秀的双向绑定原理，mvvm模型，组件，路由解析器等，非常的灵活方便，也使开发者能够着重于数据处理，让开发者更清晰的设计自己的业务。</p><p>双向绑定，就是数据变化的时候，自动触发视图的变化。</p><h1 id="实践"><a href="#实践" class="headerlink" title="实践"></a>实践</h1><p>我们都理解，vue2.0中，双向绑定的核心为<code>Object.defineProperty(obj, prop, descriptor)</code>,方法会直接在一个对象上定义一个新属性，或者修改一个对象的现有属性， 并返回这个对象</p><p>参数<code>obj</code>为<code>要在其上定义属性的对象。</code><br>参数<code>prop</code>为<code>要定义或修改的属性的名称。</code><br>参数<code>descriptor</code>为<code>将被定义或修改的属性描述符。</code></p><p>返回<code>被传递给函数的对象。</code></p><h2 id="尝试Object-defineProperty拦截用户对变量的设置"><a href="#尝试Object-defineProperty拦截用户对变量的设置" class="headerlink" title="尝试Object.defineProperty拦截用户对变量的设置"></a>尝试Object.defineProperty拦截用户对变量的设置</h2><p>我们可以新建一个项目，用来模拟及学习<code>vue</code>双向绑定的相关内容</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">+   vue相关</span><br><span class="line">+       |- 双向绑定原理</span><br><span class="line">+           |- js</span><br><span class="line">+               |- myVue.js</span><br><span class="line">+           |- index.html</span><br></pre></td></tr></table></figure><p>修改index.html中的内容，引入自己创建的myVue.js。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">+   &lt;!DOCTYPE html&gt;</span><br><span class="line">+   &lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">+   &lt;head&gt;</span><br><span class="line">+       &lt;meta charset=&quot;UTF-8&quot;&gt;</span><br><span class="line">+       &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;</span><br><span class="line">+       &lt;title&gt;Document&lt;/title&gt;</span><br><span class="line">+   &lt;/head&gt;</span><br><span class="line">+   &lt;body&gt;</span><br><span class="line">+</span><br><span class="line">+      &lt;script src=&quot;./js/myVue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">+   &lt;/body&gt;</span><br><span class="line">+   &lt;/html&gt;</span><br></pre></td></tr></table></figure></p><p>编辑<code>myVue.js</code>的内容，来尝试一下<code>Object.defineProperty(obj, prop, descriptor)</code>这个API</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">+   var data = &#123;</span><br><span class="line">+       a: 1</span><br><span class="line">+   &#125;</span><br><span class="line">+   Object.defineProperty(data, &apos;a&apos;, &#123;// 为data中的a进行拦截，读取a的时候返回自己新建的_a的值，设置a的值的时候，设置到_a上。这样，开发者对a的操作，都会映射到我们新建的虚拟的_a变量上</span><br><span class="line">+       configurable: true, //  是否允许删除属性，默认true</span><br><span class="line">+       enumerable: true, //  是否允许遍历，默认true</span><br><span class="line">+       get: function () &#123;</span><br><span class="line">+           console.log(&apos;我被读取了，返回了_a的值&apos;, this._a)</span><br><span class="line">+           return this._a</span><br><span class="line">+       &#125;,</span><br><span class="line">+       set(value) &#123;</span><br><span class="line">+           // this.a = value;</span><br><span class="line">+           this._a = value;</span><br><span class="line">+           console.log(&apos;我被设置了，被设置的值为&apos;, this._a, &apos;并放进了a的对象中&apos;)</span><br><span class="line">+       &#125;</span><br><span class="line">+   &#125;)</span><br></pre></td></tr></table></figure><p>在浏览器中，打开页面，并查看控制台，对<code>data.a</code>进行操作<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">data.a                                                              myVue.js:8 </span><br><span class="line">我被读取了，返回了_a的值 undefined</span><br><span class="line">undefined</span><br><span class="line">——————————————————————————————————————————————————————————————————————————————</span><br><span class="line">data.a = 10                                                         myVue.js:14 </span><br><span class="line">我被设置了，被设置的值为 10 并放进了a的对象中</span><br><span class="line">10</span><br><span class="line">——————————————————————————————————————————————————————————————————————————————</span><br><span class="line">data.a                                                              myVue.js:8</span><br><span class="line">我被读取了，返回了_a的值 10</span><br><span class="line">10</span><br></pre></td></tr></table></figure></p><p>可以看到，我们对data.a进行的操作，实际改变的变量是我们已经拦截的<code>_a</code>变量。<br>目前出现的问题是，第一次读取的时候，这个值没有被设置上，在下面来模拟解决方案</p><h2 id="私有变量"><a href="#私有变量" class="headerlink" title="私有变量"></a>私有变量</h2><p>声明概念<code>_</code>开头的变量一版为私有变量，外部无法访问，但是我们现在在控制台中输入并修改私有变量<code>data._a</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">data._a</span><br><span class="line">10</span><br><span class="line">——————————————————————————————————————————————————————————————————————————————</span><br><span class="line">data._a = 20</span><br><span class="line">20</span><br><span class="line">——————————————————————————————————————————————————————————————————————————————</span><br><span class="line">data._a</span><br><span class="line">20</span><br><span class="line">——————————————————————————————————————————————————————————————————————————————</span><br><span class="line">data.a                                                              myVue.js:8 </span><br><span class="line">我被读取了，返回了_a的值 20</span><br><span class="line">20</span><br></pre></td></tr></table></figure><p>却可以拿到私有变量中的<code>_a</code>的值，也可以进行无拦截的修改，这显然是我们所不希望的</p><p>所以我们可以为<code>Object.defineProperty(obj, prop, descriptor)</code>来进行封装一次，把我们理解的<code>_a</code>变成一个私有变量<br>修改<code>myVue.js</code>的内容为如下内容，<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">var data = &#123;</span><br><span class="line">    a: 1</span><br><span class="line">&#125;</span><br><span class="line">myDefineProperty(data, &apos;a&apos;)</span><br><span class="line"></span><br><span class="line">function myDefineProperty(obj,key)&#123;//对Object.defineProperty进行一次拦截，使外界无法访问私有变量value</span><br><span class="line">    var value = obj[key];</span><br><span class="line">    Object.defineProperty(obj,key,&#123;// 为data增加</span><br><span class="line">        configurable: true, //  是否允许删除属性，默认true</span><br><span class="line">        enumerable: true, //  是否允许遍历，默认true</span><br><span class="line">        get: function () &#123;</span><br><span class="line">            console.log(&apos;我被读取了，返回了value的值&apos;, value)</span><br><span class="line">            return value</span><br><span class="line">        &#125;,</span><br><span class="line">        set(newValue) &#123;</span><br><span class="line">            value = newValue;</span><br><span class="line">            console.log(&apos;我被设置了，被设置的值为&apos;, newValue, &apos;并放进了value的对象中&apos;)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>然后再查看控制台</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">data._a</span><br><span class="line">undefined</span><br><span class="line">——————————————————————————————————————————————————————————————————————————————</span><br><span class="line">data.value</span><br><span class="line">undefined</span><br><span class="line">——————————————————————————————————————————————————————————————————————————————</span><br><span class="line">data.a                                                             myVue.js:12</span><br><span class="line">我被读取了，返回了value的值 1</span><br><span class="line">1</span><br><span class="line">——————————————————————————————————————————————————————————————————————————————</span><br></pre></td></tr></table></figure><p>开发者就无法自行操作我们设计的私有变量value的内容了</p><p>自此，我们解决了，对一个对象属性的拦截，并且阻止了用户对我们设计的私有变量进行操作</p><h2 id="双向绑定实践"><a href="#双向绑定实践" class="headerlink" title="双向绑定实践"></a>双向绑定实践</h2><p>我们知道了拦截属性之后，那么就进一步来实现，一个简单的双向绑定</p><p>我们修改一下<code>index.html</code>中的内容<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">    &lt;!DOCTYPE html&gt;</span><br><span class="line">    &lt;html lang=&quot;en&quot;&gt;</span><br><span class="line">    &lt;head&gt;</span><br><span class="line">        &lt;meta charset=&quot;UTF-8&quot;&gt;</span><br><span class="line">        &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;</span><br><span class="line">        &lt;title&gt;Document&lt;/title&gt;</span><br><span class="line">+       &lt;input type=&quot;text&quot; @change=&apos;changeIpt&apos;&gt;</span><br><span class="line">+       &lt;p id=&apos;changeValue&apos;&gt;&lt;/p&gt;</span><br><span class="line">    &lt;/head&gt;</span><br><span class="line">    &lt;body&gt;</span><br><span class="line">        </span><br><span class="line">        &lt;script src=&quot;./js/myVue.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;/body&gt;</span><br><span class="line">    &lt;/html&gt;</span><br></pre></td></tr></table></figure></p><p>并在<code>myVue.js</code>中，在set中添加双向绑定的操作</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">    var data = &#123;</span><br><span class="line">        a: 1</span><br><span class="line">    &#125;</span><br><span class="line">    myDefineProperty(data, &apos;a&apos;)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">+   var ipt = document.getElementById(&apos;ipt&apos;);</span><br><span class="line">+   ipt.oninput =  function(e)&#123;</span><br><span class="line">+       data.a = e.target.value</span><br><span class="line">+   &#125;</span><br><span class="line"></span><br><span class="line">    function myDefineProperty(obj,key)&#123;</span><br><span class="line">        var value = obj[key];</span><br><span class="line">        Object.defineProperty(obj,key,&#123;// 为data增加</span><br><span class="line">            configurable: true, //  是否允许删除属性，默认true</span><br><span class="line">            enumerable: true, //  是否允许遍历，默认true</span><br><span class="line">            get: function () &#123;</span><br><span class="line">                console.log(&apos;我被读取了，返回了value的值&apos;, value)</span><br><span class="line">                return value</span><br><span class="line">            &#125;,</span><br><span class="line">            set(newValue) &#123;</span><br><span class="line">                value = newValue;</span><br><span class="line">+               document.getElementById(&apos;iptValue&apos;).innerText = newValue;</span><br><span class="line">+               ipt.value = newValue;</span><br><span class="line">                console.log(&apos;我被设置了，被设置的值为&apos;, newValue, &apos;并放进了value的对象中&apos;)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>然后我们在<code>input</code>框里输入内容，便表现出了双向绑定的能力。</p><p><a href="https://www.meixiaohan.com/file/myBlog/blog_code/vue%E7%9B%B8%E5%85%B3/%E5%8F%8C%E5%90%91%E7%BB%91%E5%AE%9A%E5%8E%9F%E7%90%86/index.html">点击查看demo</a></p><p>记得打开控制台哦！~下方为录制的屏幕，可能无法正常显示，可以点击上方demo来查看</p><video id="video" controls preload="none" poster="http://www.meixiaohan.com/file/myBlog/useFile/mvvm-video.mp4"><br>    <source id="mp4" src="http://www.meixiaohan.com/file/myBlog/useFile/mvvm-video.mp4" type="video/mp4"><br></video><p>觉得好的话，可以给我的 <a href="https://github.com/mr-xiao-han/myBlog" target="_blank" rel="noopener">github</a>点个<code>star</code>哦</p><iframe style="margin-left: 2px; margin-bottom:-5px;" frameborder="0" scrolling="0" width="100px" height="20px" src="https://ghbtns.com/github-btn.html?user=mr-xiao-han&repo=myBlog&type=star&count=true"><br></iframe>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;理解&quot;&gt;&lt;a href=&quot;#理解&quot; class=&quot;headerlink&quot; title=&quot;理解&quot;&gt;&lt;/a&gt;理解&lt;/h1&gt;&lt;p&gt;vue是一个非常优秀的框架，其优秀的双向绑定原理，mvvm模型，组件，路由解析器等，非常的灵活方便，也使开发者能够着重于数据处理，让开发者更
      
    
    </summary>
    
    
      <category term="vue" scheme="http://www.meixiaohan.com/categories/vue/"/>
    
      <category term="双向绑定" scheme="http://www.meixiaohan.com/categories/vue/%E5%8F%8C%E5%90%91%E7%BB%91%E5%AE%9A/"/>
    
      <category term="mvvm" scheme="http://www.meixiaohan.com/categories/vue/%E5%8F%8C%E5%90%91%E7%BB%91%E5%AE%9A/mvvm/"/>
    
    
      <category term="vue" scheme="http://www.meixiaohan.com/tags/vue/"/>
    
      <category term="mvvm" scheme="http://www.meixiaohan.com/tags/mvvm/"/>
    
  </entry>
  
  <entry>
    <title>javascript-请求封装</title>
    <link href="http://www.meixiaohan.com/2019/09/14/request_fengzhaung/"/>
    <id>http://www.meixiaohan.com/2019/09/14/request_fengzhaung/</id>
    <published>2019-09-13T16:00:00.000Z</published>
    <updated>2020-02-17T01:13:18.101Z</updated>
    
    <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>很多人在写前端代码的时候，都不做请求封装，这样容易出现的情况是，假设在一个项目中，有100个页面，每个页面都需要向服务器发送请求，来完成数据的交互，突然有一天，产品的哥们说，咱们得加个请求的验证，给请求交互的data里，加一个加密的数据，来保证数据的安全性，如果未进行封装的话，这100个页面中，每个请求都需要改一次，这就是个很庞大的工程，所以，我们在开始写代码的时候，对请求的封装，是一个很重要的设计</p><h1 id="理解"><a href="#理解" class="headerlink" title="理解"></a>理解</h1><p>所谓</p><h1 id="操作"><a href="#操作" class="headerlink" title="操作"></a>操作</h1><p>我们以Vue项目为例，使用vue-cli搭建项目，使axios来发送请求</p><p>文件结构如下<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">my-projext</span><br><span class="line">    |-node_modules</span><br><span class="line">    |-public</span><br><span class="line">    |-src</span><br><span class="line">        |-assets</span><br><span class="line">        |-components</span><br><span class="line">        |-router</span><br><span class="line">        |-store</span><br><span class="line">        |-views</span><br><span class="line">        |-App.vue</span><br><span class="line">        |-main.js</span><br><span class="line">    |-package.json</span><br></pre></td></tr></table></figure></p><h2 id="方法一：使用单独的文件来进行封装"><a href="#方法一：使用单独的文件来进行封装" class="headerlink" title="方法一：使用单独的文件来进行封装"></a>方法一：使用单独的文件来进行封装</h2><p>首先，在src下新建一个文件夹<code>api</code>并新建一个<code>api.js</code>文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">my-projext</span><br><span class="line">    |-node_modules</span><br><span class="line">    |-public</span><br><span class="line">    |-src</span><br><span class="line">+       |-api</span><br><span class="line">+           |-api.js</span><br><span class="line">        |-assets</span><br><span class="line">        |-components</span><br><span class="line">        |-router</span><br><span class="line">        |-store</span><br><span class="line">        |-views</span><br><span class="line">        |-App.vue</span><br><span class="line">        |-main.js</span><br><span class="line">    |-package.json</span><br></pre></td></tr></table></figure><p><code>api.js</code>添加如下内容<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">const apiUrl = &apos;https://www.yoursite.com/api/&apos;;</span><br><span class="line">const axios = require(&apos;axios&apos;);</span><br><span class="line"></span><br><span class="line">export function request(options = &#123;&#125;) &#123;</span><br><span class="line">    axios[options.methods](</span><br><span class="line">        apiUrl+options.url, </span><br><span class="line">        options.data</span><br><span class="line">    ).then(options.success)</span><br><span class="line">    .catch(options.fail)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>经过这样的封装后，在页面中使用，就变成了</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">page中</span><br><span class="line"></span><br><span class="line">import &#123;request&#125; from &apos;@/api/api.js&apos;;</span><br><span class="line">export default &#123;</span><br><span class="line">    data()&#123;</span><br><span class="line">        return &#123;&#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    methdos:&#123;</span><br><span class="line">        getData()&#123;</span><br><span class="line">            request(&#123;</span><br><span class="line">                url:&quot;getData&quot;,</span><br><span class="line">                data:&#123;</span><br><span class="line">                    param_1:&apos;入参数据&apos;</span><br><span class="line">                &#125;,</span><br><span class="line">                success:(res)=&gt;&#123;</span><br><span class="line">                    console.log(&apos;成功回调&apos;)</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>也可以在<code>main.js</code>中进行统一引入，然后注入到<code>Vue.prototype</code>中，这样就不用单独页面进行单独引入了</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">//main.js</span><br><span class="line">import &#123;request&#125; from &apos;@/api/api.js&apos;;</span><br><span class="line">Vue.prototype.$request = request;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">//Page中使用</span><br><span class="line">this.$request(&#123;</span><br><span class="line">    url:&apos;xxxxxx&apos;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p>这样的话，如果想在请求前增加<code>请求拦截</code>,只需要在公共方法中，增加一个拦截即可</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">    const apiUrl = &apos;https://www.yoursite.com/api/&apos;;</span><br><span class="line">    const axios = require(&apos;axios&apos;);</span><br><span class="line">+   const userData = require(&apos;@/api/userData.js&apos;);//引入放置用户信息的公共文件</span><br><span class="line"></span><br><span class="line">    export function request(options = &#123;&#125;) &#123;</span><br><span class="line">+       options=beforeRequest(options)</span><br><span class="line">        axios[options.methods](</span><br><span class="line">            apiUrl+options.url, </span><br><span class="line">            options.data</span><br><span class="line">-       ).then(options.success)</span><br><span class="line">+       ).then((res)=&gt;&#123;</span><br><span class="line">+           res=beforeResponse(res)</span><br><span class="line">+           options.success&amp;&amp;options.success(res)</span><br><span class="line">+       &#125;)</span><br><span class="line">        .catch(options.fail)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">+   export function beforeRequest(options = &#123;&#125;) &#123;//请求前拦截的地方</span><br><span class="line">+       options.header = options.header||&#123;&#125;</span><br><span class="line">+       options.header.token = userData.token;</span><br><span class="line">+       return options</span><br><span class="line">+   &#125;</span><br><span class="line"></span><br><span class="line">+   export function beforeResponse(res = &#123;&#125;) &#123;//收到相应后拦截的地方</span><br><span class="line">+       if(res.header.status==200)&#123;</span><br><span class="line">+           if(res.data.resCode==0)&#123;</span><br><span class="line">+               //业务成功逻辑</span><br><span class="line">+           &#125;else&#123;</span><br><span class="line">+               //业务失败逻辑</span><br><span class="line">+           &#125;</span><br><span class="line">+           return res.data;//例如，只将回调中的data交给业务，而在拦截器里统一处理状态</span><br><span class="line">+       &#125;else&#123;</span><br><span class="line">+           alert(&quot;网络错误&quot;)</span><br><span class="line">+           return res</span><br><span class="line">+       &#125;</span><br><span class="line">+   &#125;</span><br></pre></td></tr></table></figure><h2 id="方法二：Vuex中进行封装"><a href="#方法二：Vuex中进行封装" class="headerlink" title="方法二：Vuex中进行封装"></a>方法二：Vuex中进行封装</h2><p>我们将请求及请求拦截器，单独放置在vuex中的一个<code>module</code>里</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">my-projext</span><br><span class="line">    |-node_modules</span><br><span class="line">    |-public</span><br><span class="line">    |-src</span><br><span class="line">-       |-api</span><br><span class="line">-           |-api.js</span><br><span class="line">        |-store</span><br><span class="line">+           |- modules</span><br><span class="line">+               |-api.js</span><br><span class="line">            |- index.js</span><br><span class="line">        |-assets</span><br><span class="line">        |-components</span><br><span class="line">        |-router</span><br><span class="line">        |-views</span><br><span class="line">        |-App.vue</span><br><span class="line">        |-main.js</span><br><span class="line">    |-package.json</span><br></pre></td></tr></table></figure><p><code>api.js</code>中的代码为</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">const axios = require(&apos;axios&apos;);</span><br><span class="line">export default &#123;</span><br><span class="line">state: &#123;</span><br><span class="line">apiUrl:&apos;https://www.yoursite.com/api/&apos;</span><br><span class="line">&#125;,</span><br><span class="line">mutations: &#123;</span><br><span class="line"></span><br><span class="line">    &#125;，</span><br><span class="line">    actions: &#123;</span><br><span class="line">        request(&#123;state,commit,dispatch&#125;,options=&#123;&#125;)&#123;//请求方法</span><br><span class="line">           this.dispatch(&apos;beforeRequest&apos;,options).then((options)=&gt;&#123;</span><br><span class="line">                axios[options.methods](</span><br><span class="line">                    apiUrl+options.url, </span><br><span class="line">                    options.data</span><br><span class="line">                ).then((res)=&gt;&#123;</span><br><span class="line">                    return Promise.resolve(res)</span><br><span class="line">                &#125;).catch(options.fail)</span><br><span class="line">            &#125;).then((res)=&gt;&#123;</span><br><span class="line">                return this.dispatch(&apos;beforeRequest&apos;,options)</span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;,</span><br><span class="line">        beforeRequest(&#123;state,commit,dispatch&#125;,options=&#123;&#125;)&#123;//请求前拦截</span><br><span class="line">            options.header = options.header||&#123;&#125;</span><br><span class="line">            options.header.token = this.state.userData.token;</span><br><span class="line">            return Promise.resolve(options)</span><br><span class="line">        &#125;,</span><br><span class="line">        beforeResponse(&#123;state,commit,dispatch&#125;,res = &#123;&#125;) &#123;//收到相应后拦截的地方</span><br><span class="line">           if(res.header.status==200)&#123;</span><br><span class="line">               if(res.data.resCode==0)&#123;</span><br><span class="line">                   //业务成功逻辑</span><br><span class="line">               &#125;else&#123;</span><br><span class="line">                   //业务失败逻辑</span><br><span class="line">               &#125;</span><br><span class="line">               return Promise.resolve(res.data);//例如，只将回调中的data交给业务，而在拦截器里统一处理状态</span><br><span class="line">           &#125;else&#123;</span><br><span class="line">               alert(&quot;网络错误&quot;)</span><br><span class="line">               return Promise.reject(res)</span><br><span class="line">           &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>Page</code>中的代码为</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">import &#123;request&#125; from &apos;@/api/api.js&apos;;</span><br><span class="line">export default &#123;</span><br><span class="line">    data()&#123;</span><br><span class="line">        return &#123;&#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    methdos:&#123;</span><br><span class="line">        getData()&#123;</span><br><span class="line">            this.$store.dispatch(&apos;request&apos;,&#123;</span><br><span class="line">                url:&quot;getData&quot;,</span><br><span class="line">                data:&#123;</span><br><span class="line">                    param_1:&apos;入参数据&apos;</span><br><span class="line">                &#125;,</span><br><span class="line">                success:</span><br><span class="line">            &#125;).then((res)=&gt;&#123;</span><br><span class="line">                console.log(&apos;成功回调&apos;)</span><br><span class="line">            &#125;).catch(()=&gt;&#123;</span><br><span class="line">                console.log(&apos;失败回调&apos;)</span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;很多人在写前端代码的时候，都不做请求封装，这样容易出现的情况是，假设在一个项目中，有100个页面，每个页面都需要向服务器发送请求，来完成数据
      
    
    </summary>
    
    
      <category term="javascript" scheme="http://www.meixiaohan.com/categories/javascript/"/>
    
      <category term="请求封装" scheme="http://www.meixiaohan.com/categories/javascript/%E8%AF%B7%E6%B1%82%E5%B0%81%E8%A3%85/"/>
    
      <category term="拦截器" scheme="http://www.meixiaohan.com/categories/javascript/%E8%AF%B7%E6%B1%82%E5%B0%81%E8%A3%85/%E6%8B%A6%E6%88%AA%E5%99%A8/"/>
    
    
      <category term="请求封装" scheme="http://www.meixiaohan.com/tags/%E8%AF%B7%E6%B1%82%E5%B0%81%E8%A3%85/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记15-懒加载</title>
    <link href="http://www.meixiaohan.com/2019/09/11/webpack_learn_15/"/>
    <id>http://www.meixiaohan.com/2019/09/11/webpack_learn_15/</id>
    <published>2019-09-10T16:00:00.000Z</published>
    <updated>2020-02-17T01:26:20.671Z</updated>
    
    <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>懒加载的概念，意思是，使用到再加载，如果没有使用到，则不去加载</p><h1 id="理解"><a href="#理解" class="headerlink" title="理解"></a>理解</h1><p>例如，我们在写一个瀑布流的图片展示站点时，一个页面，可能会有超出屏幕数倍长度的内容，如果一次性加载所有的图片资源，会造成页面的卡顿，影响用户体验，于是有了懒加载的概念，只有滚动到这一屏幕，才会加载这一屏幕的内容（一般滚动类的会加载当前屏幕及上下各一屏幕的内容）,<code>webpack</code>中的<code>懒加载</code>，也可以这样理解。</p><h1 id="操作"><a href="#操作" class="headerlink" title="操作"></a>操作</h1><p>在上一节的基础上，对项目目录进行改造</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">webpack_learn</span><br><span class="line">|- node_modules</span><br><span class="line">|- package.json</span><br><span class="line">|- webpack.config.js</span><br><span class="line">|- yarn.lock</span><br><span class="line">|- src</span><br><span class="line">    |- let.js</span><br><span class="line">    |- get.js</span><br><span class="line">    |- index.js</span><br><span class="line">    |- math.js</span><br><span class="line">    |- print.js</span><br><span class="line">|- dist</span><br><span class="line">    |- vendors~lodash.bundle.js</span><br><span class="line">    |- bundle.js</span><br><span class="line">    |- index.html</span><br></pre></td></tr></table></figure><p>上一章节中<code>src</code>中<code>index.js</code>的内容</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">import _ from &quot;lodash&quot;;</span><br><span class="line">function getLodash()&#123;</span><br><span class="line">    return import(/* webpackChunkName: &quot;lodash&quot; */ &apos;lodash&apos;).then((_)=&gt;&#123;//这里的注释很重要，影响打包后的包名字</span><br><span class="line">        console.log(_)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line">let name = require(&apos;./let.js&apos;);</span><br><span class="line">let sayName = require(&apos;./get.js&apos;);</span><br><span class="line">sayName(&apos;大家好,我的名字是&apos;+name)</span><br><span class="line">getLodash()</span><br></pre></td></tr></table></figure><p>我们可以看到，<code>getLodash()</code>是每次都会调用的，可以设想下，如果，我们不是每次都调用，改成点击按钮才调用的话，如果用户不点击这个按钮，就不会加载了</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">    import _ from &quot;lodash&quot;;</span><br><span class="line">    function getLodash()&#123;</span><br><span class="line">        return import(/* webpackChunkName: &quot;lodash&quot; */ &apos;lodash&apos;).then((_)=&gt;&#123;//这里的注释很重要，影响打包后的包名字</span><br><span class="line">            console.log(_)</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    function createElement(tagName)&#123;</span><br><span class="line">        var element = document.createElement(tagName);</span><br><span class="line">        element.innerHTML = &apos;点击我加载lodash&apos;;</span><br><span class="line">        return element;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">+   let div = createElement(&apos;div&apos;);</span><br><span class="line">+   div.onclick=function()&#123;</span><br><span class="line">+       getLodash()</span><br><span class="line">+   &#125;</span><br><span class="line">+   document.body.appendChild(element);</span><br><span class="line"></span><br><span class="line">    let name = require(&apos;./let.js&apos;);</span><br><span class="line">    let sayName = require(&apos;./get.js&apos;);</span><br><span class="line">    sayName(&apos;大家好,我的名字是&apos;+name)</span><br><span class="line">    getLodash()</span><br></pre></td></tr></table></figure><p>这样就变成了，用户点击按钮时候，才会加载<code>lodash</code>了，这个思路可以在日常做需求的时候使用，可能更好的减少初始加载速度</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;懒加载的概念，意思是，使用到再加载，如果没有使用到，则不去加载&lt;/p&gt;
&lt;h1 id=&quot;理解&quot;&gt;&lt;a href=&quot;#理解&quot; class=&quot;h
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记14-动态导入</title>
    <link href="http://www.meixiaohan.com/2019/09/09/webpack_learn_14/"/>
    <id>http://www.meixiaohan.com/2019/09/09/webpack_learn_14/</id>
    <published>2019-09-08T16:00:00.000Z</published>
    <updated>2020-02-17T01:16:28.081Z</updated>
    
    <content type="html"><![CDATA[<p>webpack还支持一种动态的模块导入方式</p><p>清理一下文件并新增一个生产与开发环境及通用配置的<code>webpack.config.js</code>文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">webpack_learn</span><br><span class="line">|- node_modules</span><br><span class="line">|- package.json</span><br><span class="line">|- webpack.config.js</span><br><span class="line">|- yarn.lock</span><br><span class="line">|- src</span><br><span class="line">    |- let.js</span><br><span class="line">    |- get.js</span><br><span class="line">    |- index.js</span><br><span class="line">    |- math.js</span><br><span class="line">|- dist</span><br><span class="line">    |- bundle.js</span><br><span class="line">    |- index.html</span><br></pre></td></tr></table></figure><p>修改<code>config</code>文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">const path = require(&apos;path&apos;);</span><br><span class="line">const HTMLWebpackPlugin = require(&apos;html-webpack-plugin&apos;);</span><br><span class="line">const webpack = require(&apos;webpack&apos;);</span><br><span class="line">const &#123;</span><br><span class="line">    CleanWebpackPlugin</span><br><span class="line">&#125; = require(&apos;clean-webpack-plugin&apos;);</span><br><span class="line"></span><br><span class="line">module.exports = &#123;</span><br><span class="line">    entry: &#123;</span><br><span class="line">      index: &apos;./src/index.js&apos;,</span><br><span class="line">-     index2: &apos;./src/index2.js&apos;,</span><br><span class="line">-     math: &apos;./src/math.js&apos;,</span><br><span class="line">    &#125;,</span><br><span class="line">    plugins: [</span><br><span class="line">        new CleanWebpackPlugin(),</span><br><span class="line">        new HTMLWebpackPlugin(&#123;</span><br><span class="line">            title: &apos;Code Splitting&apos;</span><br><span class="line">        &#125;)</span><br><span class="line">    ],</span><br><span class="line">-   optimization: &#123;</span><br><span class="line">-       splitChunks: &#123;</span><br><span class="line">-           cacheGroups: &#123;</span><br><span class="line">-               commons: &#123;</span><br><span class="line">-                   name: &quot;commons&quot;,</span><br><span class="line">-                   chunks: &quot;all&quot;,</span><br><span class="line">-                   minChunks: 2</span><br><span class="line">-               &#125;</span><br><span class="line">-           &#125;</span><br><span class="line">-       &#125;</span><br><span class="line">-   &#125;,</span><br><span class="line">    output: &#123;</span><br><span class="line">        filename: &apos;[name].bundle.js&apos;,</span><br><span class="line">+       chunkFilename: &apos;[name].bundle.js&apos;,</span><br><span class="line">        path: path.resolve(__dirname, &apos;dist&apos;)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>然后修改<code>src</code>中<code>index.js</code>的内容</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">-   import _ from &quot;lodash&quot;;</span><br><span class="line">+   function getLodash()&#123;</span><br><span class="line">+       return import(/* webpackChunkName: &quot;lodash&quot; */ &apos;lodash&apos;).then((_)=&gt;&#123;//这里的注释很重要，影响打包后的包名字</span><br><span class="line">+           console.log(_)</span><br><span class="line">+       &#125;)</span><br><span class="line">+   &#125;</span><br><span class="line">    let name = require(&apos;./let.js&apos;);</span><br><span class="line">    let sayName = require(&apos;./get.js&apos;);</span><br><span class="line">    sayName(&apos;大家好,我的名字是&apos;+name)</span><br><span class="line">+   getLodash()</span><br></pre></td></tr></table></figure><p>然后执行打包指令</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build # 或者 yarn build</span><br></pre></td></tr></table></figure><p>然后可以看到，文件目录结构变成了</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">       webpack_learn</span><br><span class="line">       |- node_modules</span><br><span class="line">       |- package.json</span><br><span class="line">       |- webpack.config.js</span><br><span class="line">       |- yarn.lock</span><br><span class="line">       |- src</span><br><span class="line">           |- let.js</span><br><span class="line">           |- get.js</span><br><span class="line">           |- index.js</span><br><span class="line">           |- math.js</span><br><span class="line">       |- dist</span><br><span class="line">+          |- vendors~lodash.bundle.js</span><br><span class="line">           |- bundle.js</span><br><span class="line">           |- index.html</span><br></pre></td></tr></table></figure><p>这样动态引入的<code>lodash</code>就被打包进入了<code>vendors~lodash.bundle.js</code>文件中，从而完成了模块的动态导入</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;webpack还支持一种动态的模块导入方式&lt;/p&gt;
&lt;p&gt;清理一下文件并新增一个生产与开发环境及通用配置的&lt;code&gt;webpack.config.js&lt;/code&gt;文件&lt;/p&gt;
&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td 
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记13-代码分离</title>
    <link href="http://www.meixiaohan.com/2019/09/06/webpack_learn_13/"/>
    <id>http://www.meixiaohan.com/2019/09/06/webpack_learn_13/</id>
    <published>2019-09-05T16:00:00.000Z</published>
    <updated>2020-02-10T03:01:22.118Z</updated>
    
    <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>针对一个多页面向目来讲，我们希望每个包的体积都更小一些。</p><h1 id="方案"><a href="#方案" class="headerlink" title="方案"></a>方案</h1><p>可以使用webpack的提供的三种分离方案</p><ul><li>入口起点：使用 entry 配置手动地分离代码。</li><li>防止重复：使用 CommonsChunkPlugin 去重和分离 chunk。</li><li>动态导入：通过模块的内联函数调用来分离代码。</li></ul><h1 id="写法"><a href="#写法" class="headerlink" title="写法"></a>写法</h1><h2 id="使用-entry-配置手动地分离代码。"><a href="#使用-entry-配置手动地分离代码。" class="headerlink" title="使用 entry 配置手动地分离代码。"></a>使用 entry 配置手动地分离代码。</h2><p>清理一下文件并新增一个生产与开发环境及通用配置的<code>config</code>文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">       webpack_learn</span><br><span class="line">       |- node_modules</span><br><span class="line">       |- package.json</span><br><span class="line">+      |- webpack.config.js</span><br><span class="line">-      |- webpack.common.js</span><br><span class="line">-      |- webpack.dev.js</span><br><span class="line">-      |- webpack.prod.js</span><br><span class="line">       |- yarn.lock</span><br><span class="line">       |- src</span><br><span class="line">           |- let.js</span><br><span class="line">           |- get.js</span><br><span class="line">           |- index.js</span><br><span class="line">           |- math.js</span><br><span class="line">       |- dist</span><br><span class="line">           |- bundle.js</span><br><span class="line">           |- index.html</span><br></pre></td></tr></table></figure><p>修改新增的配置文件内容</p><p>修改 <code>webpack.config.js</code> 文件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">const path = require(&apos;path&apos;);</span><br><span class="line">const HTMLWebpackPlugin = require(&apos;html-webpack-plugin&apos;);</span><br><span class="line">const &#123; CleanWebpackPlugin &#125; = require(&apos;clean-webpack-plugin&apos;);</span><br><span class="line">module.exports = &#123;</span><br><span class="line">  entry: &#123;</span><br><span class="line">    index: &apos;./src/index.js&apos;,</span><br><span class="line">    math: &apos;./src/math.js&apos;</span><br><span class="line">  &#125;,</span><br><span class="line">  plugins: [</span><br><span class="line">new CleanWebpackPlugin(),</span><br><span class="line">    new HTMLWebpackPlugin(&#123;</span><br><span class="line">      title: &apos;Code Splitting&apos;</span><br><span class="line">    &#125;)</span><br><span class="line">  ],</span><br><span class="line">  output: &#123;</span><br><span class="line">    filename: &apos;[name].bundle.js&apos;,</span><br><span class="line">    path: path.resolve(__dirname, &apos;dist&apos;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p><p>然后修改<code>package.json</code>中的<code>scripts</code>快捷指令</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  &quot;dependencies&quot;: &#123;</span><br><span class="line">    &quot;babel-loader&quot;: &quot;^8.0.6&quot;,</span><br><span class="line">    &quot;clean-webpack-plugin&quot;: &quot;^3.0.0&quot;,</span><br><span class="line">    &quot;copy-webpack-plugin&quot;: &quot;^5.1.1&quot;,</span><br><span class="line">    &quot;html-webpack-plugin&quot;: &quot;^3.2.0&quot;,</span><br><span class="line">    &quot;webpack&quot;: &quot;^4.41.5&quot;,</span><br><span class="line">    &quot;webpack-cli&quot;: &quot;^3.3.10&quot;,</span><br><span class="line">    &quot;webpack-dev-server&quot;: &quot;^3.10.1&quot;,</span><br><span class="line">    &quot;webpack-merge&quot;: &quot;^4.2.2&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;name&quot;: &quot;webpack_learn&quot;,</span><br><span class="line">  &quot;sideEffects&quot;: false,</span><br><span class="line">  &quot;version&quot;: &quot;1.0.0&quot;,</span><br><span class="line">  &quot;main&quot;: &quot;index.js&quot;,</span><br><span class="line">  &quot;devDependencies&quot;: &#123;</span><br><span class="line">    &quot;@babel/core&quot;: &quot;^7.7.7&quot;,</span><br><span class="line">    &quot;@babel/preset-env&quot;: &quot;^7.7.7&quot;,</span><br><span class="line">    &quot;babel-core&quot;: &quot;^6.26.3&quot;,</span><br><span class="line">    &quot;babel-preset-env&quot;: &quot;^1.7.0&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;scripts&quot;: &#123;</span><br><span class="line">+   &quot;build&quot;: &quot;webpack --config webpack.config.js&quot;,</span><br><span class="line">-   &quot;build&quot;: &quot;webpack --config webpack.prod.js&quot;,</span><br><span class="line">-   &quot;serve&quot;: &quot;webpack-dev-server --open --config webpack.dev.js&quot;,</span><br><span class="line">    &quot;watch&quot;: &quot;webpack --watch&quot;,</span><br><span class="line">    &quot;dev&quot;: &quot;webpack --mode development&quot;,</span><br><span class="line">    &quot;product&quot;: &quot;webpack --mode production&quot;,</span><br><span class="line">    &quot;testParams&quot;: &quot;webpack --mode production --env.production product --param1 1 --param2 2 --explane 这是一个说明&quot;,</span><br><span class="line">    &quot;showColorAndProgress&quot;: &quot;webpack --progress --colors&quot;,</span><br><span class="line">    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;author&quot;: &quot;&quot;,</span><br><span class="line">  &quot;license&quot;: &quot;ISC&quot;,</span><br><span class="line">  &quot;description&quot;: &quot;&quot;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>修改一下<code>index.js</code>的内容<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">let name = require(&apos;./let.js&apos;);</span><br><span class="line">let sayName = require(&apos;./get.js&apos;);</span><br><span class="line">sayName(&apos;大家好,我的名字是&apos;+name)</span><br></pre></td></tr></table></figure></p><p>然后执行打包指令<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build #也可以yarn build 打包生产环境</span><br></pre></td></tr></table></figure></p><p>index.bundle.js<br>打包后可以看到编译的结果</p> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">       webpack_learn</span><br><span class="line">       |- node_modules</span><br><span class="line">       |- package.json</span><br><span class="line">       |- webpack.config.js</span><br><span class="line">       |- yarn.lock</span><br><span class="line">       |- src</span><br><span class="line">           |- let.js</span><br><span class="line">           |- get.js</span><br><span class="line">           |- index.js</span><br><span class="line">           |- math.js</span><br><span class="line">       |- dist</span><br><span class="line">-          |- bundle.js</span><br><span class="line">-          |- index.html</span><br><span class="line">+          |- index.html</span><br><span class="line">+          |- index.bundle.js</span><br><span class="line">+          |- math.bundle.js</span><br></pre></td></tr></table></figure><p>并且<code>index.html</code>中的内容如下，引入了两个<code>js</code>文件，而且，<code>index.js</code>及<code>math.js</code>中的代码被分离开了，达成了通过<code>entry</code>的配置方式进行分离</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">  &lt;head&gt;</span><br><span class="line">    &lt;meta charset=&quot;UTF-8&quot;&gt;</span><br><span class="line">    &lt;title&gt;Code Splitting&lt;/title&gt;</span><br><span class="line">  &lt;/head&gt;</span><br><span class="line">  &lt;body&gt;</span><br><span class="line">  &lt;script type=&quot;text/javascript&quot; src=&quot;index.bundle.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">  &lt;script type=&quot;text/javascript&quot; src=&quot;math.bundle.js&quot;&gt;&lt;/script&gt;</span><br><span class="line">  &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure><h2 id="使用-CommonsChunkPlugin-去重和分离-chunk"><a href="#使用-CommonsChunkPlugin-去重和分离-chunk" class="headerlink" title="使用 CommonsChunkPlugin 去重和分离 chunk"></a>使用 CommonsChunkPlugin 去重和分离 chunk</h2><p><code>CommonsChunkPlugin</code> 插件可以将公共的依赖模块提取到已有的入口 chunk 中，或者提取到一个新生成的 chunk。</p><p>继续修改文件目录<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">       webpack_learn</span><br><span class="line">       |- node_modules</span><br><span class="line">       |- package.json</span><br><span class="line">       |- webpack.config.js</span><br><span class="line">       |- yarn.lock</span><br><span class="line">       |- src</span><br><span class="line">           |- let.js</span><br><span class="line">           |- get.js</span><br><span class="line">           |- index.js</span><br><span class="line">+          |- index2.js</span><br><span class="line">           |- math.js</span><br><span class="line">       |- dist</span><br><span class="line">           |- index.html</span><br><span class="line">           |- index.bundle.js</span><br><span class="line">           |- math.bundle.js</span><br></pre></td></tr></table></figure></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">//index2.js</span><br><span class="line">+    let name = require(&apos;./let.js&apos;);</span><br><span class="line">+    let sayName = require(&apos;./get.js&apos;);</span><br><span class="line">+    sayName(&apos;大家好,我的名字2是&apos;+name)</span><br></pre></td></tr></table></figure><p>修改 <code>webpack.config.js</code> 文件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">const path = require(&apos;path&apos;);</span><br><span class="line">const HTMLWebpackPlugin = require(&apos;html-webpack-plugin&apos;);</span><br><span class="line">const &#123; CleanWebpackPlugin &#125; = require(&apos;clean-webpack-plugin&apos;);</span><br><span class="line">module.exports = &#123;</span><br><span class="line">  entry: &#123;</span><br><span class="line">    index: &apos;./src/index.js&apos;,</span><br><span class="line">    index2: &apos;./src/index2.js&apos;,</span><br><span class="line">    math: &apos;./src/math.js&apos;</span><br><span class="line">  &#125;,</span><br><span class="line">  plugins: [</span><br><span class="line">new CleanWebpackPlugin(),</span><br><span class="line">    new HTMLWebpackPlugin(&#123;</span><br><span class="line">      title: &apos;Code Splitting&apos;</span><br><span class="line">    &#125;)</span><br><span class="line">  ],</span><br><span class="line">  output: &#123;</span><br><span class="line">    filename: &apos;[name].bundle.js&apos;,</span><br><span class="line">    path: path.resolve(__dirname, &apos;dist&apos;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p><p>然后执行打包指令<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build #也可以yarn build 打包生产环境</span><br></pre></td></tr></table></figure></p><p>然后可以看到，<code>index2.bundle.js</code>与<code>index.bundle.js</code>中，均出现了重复的代码</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">([function(e,t)&#123;e.exports=&quot;小明&quot;&#125;,function(e,t)&#123;e.exports=function(e)&#123;console.log(e)&#125;&#125;</span><br></pre></td></tr></table></figure><p>为了解决这种情况，可以使用<code>CommonsChunkPlugin</code> 去重和分离 chunk</p><p>修改 <code>webpack.config.js</code> 文件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">    const path = require(&apos;path&apos;);</span><br><span class="line">    const HTMLWebpackPlugin = require(&apos;html-webpack-plugin&apos;);</span><br><span class="line">+   const webpack = require(&apos;webpack&apos;);</span><br><span class="line">    const &#123; CleanWebpackPlugin &#125; = require(&apos;clean-webpack-plugin&apos;);</span><br><span class="line">    module.exports = &#123;</span><br><span class="line">      entry: &#123;</span><br><span class="line">        index: &apos;./src/index.js&apos;,</span><br><span class="line">        index2: &apos;./src/index2.js&apos;,</span><br><span class="line">        math: &apos;./src/math.js&apos;</span><br><span class="line">      &#125;,</span><br><span class="line">      plugins: [</span><br><span class="line">    new CleanWebpackPlugin(),</span><br><span class="line">        new HTMLWebpackPlugin(&#123;</span><br><span class="line">          title: &apos;Code Splitting&apos;</span><br><span class="line">-       &#125;)</span><br><span class="line">+      &#125;),</span><br><span class="line">+      new webpack.optimize.CommonsChunkPlugin(&#123;</span><br><span class="line">+        name: &apos;common&apos; // 指定公共 bundle 的名称。</span><br><span class="line">+      &#125;)</span><br><span class="line">      ],</span><br><span class="line">      output: &#123;</span><br><span class="line">        filename: &apos;[name].bundle.js&apos;,</span><br><span class="line">        path: path.resolve(__dirname, &apos;dist&apos;)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;;</span><br></pre></td></tr></table></figure></p><p>然后执行打包指令<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build #也可以yarn build 打包生产环境</span><br></pre></td></tr></table></figure></p><p>此时打包报错了，提示信息<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Error: webpack.optimize.CommonsChunkPlugin has been removed, please use config.optimization.splitChunks instead.</span><br></pre></td></tr></table></figure></p><p>修改 <code>webpack.config.js</code> 文件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">    const path = require(&apos;path&apos;);</span><br><span class="line">    const HTMLWebpackPlugin = require(&apos;html-webpack-plugin&apos;);</span><br><span class="line">-   const webpack = require(&apos;webpack&apos;);</span><br><span class="line">    const &#123; CleanWebpackPlugin &#125; = require(&apos;clean-webpack-plugin&apos;);</span><br><span class="line">    module.exports = &#123;</span><br><span class="line">      entry: &#123;</span><br><span class="line">        index: &apos;./src/index.js&apos;,</span><br><span class="line">        index2: &apos;./src/index2.js&apos;,</span><br><span class="line">        math: &apos;./src/math.js&apos;</span><br><span class="line">      &#125;,</span><br><span class="line">      plugins: [</span><br><span class="line">    new CleanWebpackPlugin(),</span><br><span class="line">        new HTMLWebpackPlugin(&#123;</span><br><span class="line">          title: &apos;Code Splitting&apos;</span><br><span class="line">-      &#125;),</span><br><span class="line">-      new webpack.optimize.CommonsChunkPlugin(&#123;</span><br><span class="line">-        name: &apos;common&apos; // 指定公共 bundle 的名称。</span><br><span class="line">-      &#125;)</span><br><span class="line">    ],</span><br><span class="line">  </span><br><span class="line">+    optimization: &#123;</span><br><span class="line">+    splitChunks: &#123;</span><br><span class="line">+        cacheGroups: &#123;</span><br><span class="line">+            commons: &#123;</span><br><span class="line">+                name: &quot;commons&quot;,</span><br><span class="line">+                chunks: &quot;all&quot;,</span><br><span class="line">+                minChunks: 2</span><br><span class="line">+            &#125;</span><br><span class="line">+        &#125;</span><br><span class="line">+        &#125;</span><br><span class="line">+    &#125;,</span><br><span class="line">      output: &#123;</span><br><span class="line">        filename: &apos;[name].bundle.js&apos;,</span><br><span class="line">        path: path.resolve(__dirname, &apos;dist&apos;)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;;</span><br></pre></td></tr></table></figure></p><p><code>webpack.optimize.CommonsChunkPlugin</code>这个模块被移除了，请使用<code>config.optimization.splitChunks</code>代替，查询<a href="https://webpack.js.org/plugins/split-chunks-plugin/" target="_blank" rel="noopener">文档地址</a></p><p>但是我们发现，再次打包，也没有单独生成一个我们命名的<code>commons.bundle.js</code></p><p>初步怀疑是，公共代码包里的代码体积过小，导致的没有打包，我们将<code>index.js</code>和<code>index2.js</code>中引入一个巨大的<code>lodash</code>模块再来尝试一下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">//index.js</span><br><span class="line">+   import _ from &apos;lodash&apos;;</span><br><span class="line">let name = require(&apos;./let.js&apos;);</span><br><span class="line">    let sayName = require(&apos;./get.js&apos;);</span><br><span class="line">    sayName(&apos;大家好,我的名字是&apos;+name)</span><br><span class="line"></span><br><span class="line">//index2.js</span><br><span class="line">+   import _ from &apos;lodash&apos;;</span><br><span class="line">let name = require(&apos;./let.js&apos;);</span><br><span class="line">    let sayName = require(&apos;./get.js&apos;);</span><br><span class="line">    sayName(&apos;大家好,我的名字2是&apos;+name)</span><br></pre></td></tr></table></figure><p>然后执行打包指令<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build #也可以yarn build 打包生产环境</span><br></pre></td></tr></table></figure></p><p>打包结果如下</p><table><thead><tr><th style="text-align:center">Asset</th><th style="text-align:center">Size</th><th style="text-align:center">Chunks</th><th style="text-align:center">Chunk Names</th></tr></thead><tbody><tr><td style="text-align:center"> commons.bundle.js</td><td style="text-align:center">71.1 KiB</td><td style="text-align:center">0  [emitted]</td><td style="text-align:center">commons</td></tr><tr><td style="text-align:center">   index.bundle.js</td><td style="text-align:center">1.64 KiB</td><td style="text-align:center">1  [emitted]</td><td style="text-align:center">index</td></tr><tr><td style="text-align:center">        index.html</td><td style="text-align:center">379 bytes</td><td style="text-align:center">[emitted]</td><td style="text-align:center"></td></tr><tr><td style="text-align:center">  index2.bundle.js</td><td style="text-align:center">1.58 KiB</td><td style="text-align:center">2  [emitted]</td><td style="text-align:center">index2</td></tr><tr><td style="text-align:center">    math.bundle.js</td><td style="text-align:center">1.18 KiB</td><td style="text-align:center">3  [emitted]</td><td style="text-align:center">math</td></tr></tbody></table><p>可以看到，<code>lodash</code>模块被打包进了<code>commons.bundle.js</code>从而实现了公共代码的分离</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;针对一个多页面向目来讲，我们希望每个包的体积都更小一些。&lt;/p&gt;
&lt;h1 id=&quot;方案&quot;&gt;&lt;a href=&quot;#方案&quot; class=&quot;head
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记12-生产环境构建</title>
    <link href="http://www.meixiaohan.com/2019/09/03/webpack_learn_12/"/>
    <id>http://www.meixiaohan.com/2019/09/03/webpack_learn_12/</id>
    <published>2019-09-02T16:00:00.000Z</published>
    <updated>2020-01-21T09:09:35.763Z</updated>
    
    <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>通常，我们在开发一个应用的时候，会有生产环境与开发环境的概念，生产环境中，我们需要体积最小的代码，以及图片等静态文件使用<code>cdn</code>上的服务，开发环境上，需要热更新，source-map等来快速排错，目标不同。</p><h1 id="方案"><a href="#方案" class="headerlink" title="方案"></a>方案</h1><p>我们可以分别为生产环境与测试环境编写一个配置文件，并且使用<code>webpack-merge</code>来组合通用配置及专属配置。</p><h1 id="写法"><a href="#写法" class="headerlink" title="写法"></a>写法</h1><ol><li><p>首先安装<code>webpack-merge</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install webpack-merge # 或者yarn add webpack-merge</span><br></pre></td></tr></table></figure></li><li><p>清理一下文件并新增一个生产与开发环境及通用配置的<code>config</code>文件，<code>webpack.common.js</code>、<code>webpack.dev.js</code>、<code>webpack.prod.js</code>。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">       webpack_learn</span><br><span class="line">       |- node_modules</span><br><span class="line">       |- package.json</span><br><span class="line">-      |- webpack.config.js</span><br><span class="line">+      |- webpack.common.js</span><br><span class="line">+      |- webpack.dev.js</span><br><span class="line">+      |- webpack.prod.js</span><br><span class="line">       |- yarn.lock</span><br><span class="line">       |- src</span><br><span class="line">           |- let.js</span><br><span class="line">           |- get.js</span><br><span class="line">           |- index.js</span><br><span class="line">-          |- math.js</span><br><span class="line">       |- dist</span><br><span class="line">           |- bundle.js</span><br><span class="line">           |- index.html</span><br></pre></td></tr></table></figure></li></ol><p>修改新增的配置文件内容</p><p><code>webpack.common.js</code>通用文件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">+     const path = require(&apos;path&apos;);</span><br><span class="line">+     const &#123; CleanWebpackPlugin &#125; = require(&apos;clean-webpack-plugin&apos;);</span><br><span class="line">+     const HtmlWebpackPlugin = require(&apos;html-webpack-plugin&apos;);</span><br><span class="line">+     </span><br><span class="line">+     module.exports = &#123;</span><br><span class="line">+       entry: &#123;</span><br><span class="line">+         app: &apos;./src/index.js&apos;</span><br><span class="line">+       &#125;,</span><br><span class="line">+       plugins: [</span><br><span class="line">+         new CleanWebpackPlugin(),</span><br><span class="line">+         new HtmlWebpackPlugin(&#123;</span><br><span class="line">+           title: &apos;Production&apos;</span><br><span class="line">+         &#125;)</span><br><span class="line">+       ],</span><br><span class="line">+       output: &#123;</span><br><span class="line">+         filename: &apos;[name].bundle.js&apos;,</span><br><span class="line">+         path: path.resolve(__dirname, &apos;dist&apos;)</span><br><span class="line">+       &#125;</span><br><span class="line">+     &#125;;</span><br></pre></td></tr></table></figure></p><p><code>webpack.dev.js</code>开发环境配置文件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">+     const merge = require(&apos;webpack-merge&apos;);</span><br><span class="line">+     const common = require(&apos;./webpack.common.js&apos;);</span><br><span class="line">+     </span><br><span class="line">+     module.exports = merge(common, &#123;</span><br><span class="line">+       devtool: &apos;inline-source-map&apos;,</span><br><span class="line">+       devServer: &#123;</span><br><span class="line">+         contentBase: &apos;./dist&apos;</span><br><span class="line">+       &#125;</span><br><span class="line">+     &#125;);</span><br></pre></td></tr></table></figure></p><p><code>webpack.prod.js</code>生产环境配置文件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">+     const merge = require(&apos;webpack-merge&apos;);</span><br><span class="line">+     const UglifyJSPlugin = require(&apos;uglifyjs-webpack-plugin&apos;);</span><br><span class="line">+     const common = require(&apos;./webpack.common.js&apos;);</span><br><span class="line">+     </span><br><span class="line">+     module.exports = merge(common, &#123;</span><br><span class="line">+       plugins: [</span><br><span class="line">+         new UglifyJSPlugin()</span><br><span class="line">+       ]</span><br><span class="line">+     &#125;);</span><br></pre></td></tr></table></figure></p><ol><li>无论生产环境还是开发环境，都清理<code>dist</code>目录，新建<code>index.html</code></li><li>开发环境基于<code>dist</code>目录建立本地服务器，并添加<code>source-map</code>来快速排错，且使用<code>webpack-merge</code>来合并<code>webpack.common.js</code>通用配置文件中的配置内容</li><li>生产环境开启摇树优化<code>tree-shakeing</code>，且使用<code>webpack-merge</code>来合并<code>webpack.common.js</code>通用配置文件中的配置内容</li></ol><p>然后修改<code>package.json</code>中的<code>scripts</code>快捷指令</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  &quot;dependencies&quot;: &#123;</span><br><span class="line">    &quot;babel-loader&quot;: &quot;^8.0.6&quot;,</span><br><span class="line">    &quot;clean-webpack-plugin&quot;: &quot;^3.0.0&quot;,</span><br><span class="line">    &quot;copy-webpack-plugin&quot;: &quot;^5.1.1&quot;,</span><br><span class="line">    &quot;html-webpack-plugin&quot;: &quot;^3.2.0&quot;,</span><br><span class="line">    &quot;webpack&quot;: &quot;^4.41.5&quot;,</span><br><span class="line">    &quot;webpack-cli&quot;: &quot;^3.3.10&quot;,</span><br><span class="line">    &quot;webpack-dev-server&quot;: &quot;^3.10.1&quot;,</span><br><span class="line">    &quot;webpack-merge&quot;: &quot;^4.2.2&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;name&quot;: &quot;webpack_learn&quot;,</span><br><span class="line">  &quot;sideEffects&quot;: false,</span><br><span class="line">  &quot;version&quot;: &quot;1.0.0&quot;,</span><br><span class="line">  &quot;main&quot;: &quot;index.js&quot;,</span><br><span class="line">  &quot;devDependencies&quot;: &#123;</span><br><span class="line">    &quot;@babel/core&quot;: &quot;^7.7.7&quot;,</span><br><span class="line">    &quot;@babel/preset-env&quot;: &quot;^7.7.7&quot;,</span><br><span class="line">    &quot;babel-core&quot;: &quot;^6.26.3&quot;,</span><br><span class="line">    &quot;babel-preset-env&quot;: &quot;^1.7.0&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;scripts&quot;: &#123;</span><br><span class="line">-   &quot;build&quot;: &quot;webpack&quot;,</span><br><span class="line">+   &quot;build&quot;: &quot;webpack --config webpack.prod.js&quot;,</span><br><span class="line">-   &quot;serve&quot;: &quot;webpack-dev-server --open&quot;,</span><br><span class="line">+   &quot;serve&quot;: &quot;webpack-dev-server --open --config webpack.dev.js&quot;,</span><br><span class="line">    &quot;watch&quot;: &quot;webpack --watch&quot;,</span><br><span class="line">    &quot;dev&quot;: &quot;webpack --mode development&quot;,</span><br><span class="line">    &quot;product&quot;: &quot;webpack --mode production&quot;,</span><br><span class="line">    &quot;testParams&quot;: &quot;webpack --mode production --env.production product --param1 1 --param2 2 --explane 这是一个说明&quot;,</span><br><span class="line">    &quot;showColorAndProgress&quot;: &quot;webpack --progress --colors&quot;,</span><br><span class="line">    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;author&quot;: &quot;&quot;,</span><br><span class="line">  &quot;license&quot;: &quot;ISC&quot;,</span><br><span class="line">  &quot;description&quot;: &quot;&quot;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后执行打包指令<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm run serve #也可以yarn serve 运行开发环境</span><br><span class="line">npm run build #也可以yarn build 打包生产环境</span><br></pre></td></tr></table></figure></p><p>可以看到报了个错</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ERROR in app.bundle.js from UglifyJs</span><br><span class="line">Unexpected token: name «name», expected: punc «;» [app.bundle.js:91,4]</span><br></pre></td></tr></table></figure><p>这个问题在于，<code>UglifyJs</code>对<code>es6</code>语法的解析有问题，需要转成<code>es5</code>后再次打包</p><p><code>webpack.prod.js</code>中增加babel配置</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">    const merge = require(&apos;webpack-merge&apos;);</span><br><span class="line">    const UglifyJSPlugin = require(&apos;uglifyjs-webpack-plugin&apos;);</span><br><span class="line">    const common = require(&apos;./webpack.common.js&apos;);</span><br><span class="line">    </span><br><span class="line">    module.exports = merge(common, &#123;</span><br><span class="line">+       module: &#123;</span><br><span class="line">+           rules: [&#123;</span><br><span class="line">+               //里面为匹配的规则</span><br><span class="line">+               test: /\.m?js$/,</span><br><span class="line">+               exclude: /(node_modules|bower_components)/,</span><br><span class="line">+               use: &#123;</span><br><span class="line">+                   loader: &apos;babel-loader&apos;,</span><br><span class="line">+                   options: &#123;</span><br><span class="line">+                       presets: [&apos;@babel/preset-env&apos;]</span><br><span class="line">+                   &#125;</span><br><span class="line">+               &#125;</span><br><span class="line">+           &#125;]</span><br><span class="line">+       &#125;,</span><br><span class="line">        plugins: [</span><br><span class="line">            new UglifyJSPlugin()</span><br><span class="line">        ]</span><br><span class="line">    &#125;);</span><br></pre></td></tr></table></figure><p>然后执行打包</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build #也可以yarn build 打包生产环境</span><br></pre></td></tr></table></figure><p>就打爆了生产版本，经过了tree-shaking的版本</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;通常，我们在开发一个应用的时候，会有生产环境与开发环境的概念，生产环境中，我们需要体积最小的代码，以及图片等静态文件使用&lt;code&gt;cdn&lt;
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记11-tree shaking</title>
    <link href="http://www.meixiaohan.com/2019/09/01/webpack_learn_11/"/>
    <id>http://www.meixiaohan.com/2019/09/01/webpack_learn_11/</id>
    <published>2019-08-31T16:00:00.000Z</published>
    <updated>2020-01-20T04:14:54.845Z</updated>
    
    <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>由于，我们在开发过程中，会引入很多大大小小的模块，比如一个计算方法通用的大包，封装了很多很多的方法，但是我们只用到了其中一两个方法，往往希望，打包只打包使用到的方法，未使用到的方法，不被打包进最后的代码中，以保持体积的最小化。</p><h1 id="方案"><a href="#方案" class="headerlink" title="方案"></a>方案</h1><p>webpack为这种情况，提供了tree shaking</p><h1 id="写法"><a href="#写法" class="headerlink" title="写法"></a>写法</h1><ol><li>清理一下文件并新增一个<code>math.js</code>。</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">   webpack_learn</span><br><span class="line">   |- node_modules</span><br><span class="line">   |- package.json</span><br><span class="line">   |- webpack.config.js</span><br><span class="line">   |- yarn.lock</span><br><span class="line">-  |- staticFrom</span><br><span class="line">-      |- test.txt</span><br><span class="line">   |- src</span><br><span class="line">       |- let.js</span><br><span class="line">       |- get.js</span><br><span class="line">       |- index.js</span><br><span class="line">+      |- math.js</span><br><span class="line">   |- dist</span><br><span class="line">       |- bundle.js</span><br><span class="line">-      |- main.js</span><br><span class="line">       |- index.html</span><br><span class="line">-      |- test.txt</span><br></pre></td></tr></table></figure><ol start="2"><li>修改<code>math.js</code>的内容</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">    //math.js</span><br><span class="line">+   export function square(x) &#123;//平方</span><br><span class="line">+     return x * x;</span><br><span class="line">+   &#125;</span><br><span class="line">+   </span><br><span class="line">+   export function cube(x) &#123;//立方</span><br><span class="line">+     return x * x * x;</span><br><span class="line">+   &#125;</span><br><span class="line">+   </span><br><span class="line">+   export function add(x,y) &#123;//求和</span><br><span class="line">+     return x + y;</span><br><span class="line">+   &#125;</span><br><span class="line">+   </span><br><span class="line">+   export function cut(x,y) &#123;//计算差</span><br><span class="line">+     return x - y;</span><br><span class="line">+   &#125;</span><br></pre></td></tr></table></figure><p>修改<code>index.js</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">    let name = require(&apos;./let.js&apos;);</span><br><span class="line">    let sayName = require(&apos;./get.js&apos;);</span><br><span class="line">+   let math = require(&apos;./math.js&apos;);</span><br><span class="line">    </span><br><span class="line">    sayName(&apos;大家好,我的名字是&apos;+name)</span><br><span class="line">+   console.log(math.add(2,3))</span><br><span class="line">+   console.log(math.add(9,18))</span><br></pre></td></tr></table></figure><p>然后执行打包指令<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build #也可以yarn build</span><br></pre></td></tr></table></figure></p><p>打包后的代码如下<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">!function(n)&#123;var t=&#123;&#125;;function e(r)&#123;if(t[r])return t[r].exports;var o=t[r]=&#123;i:r,l:!1,exports:&#123;&#125;&#125;;return n[r].call(o.exports,o,o.exports,e),o.l=!0,o.exports&#125;e.m=n,e.c=t,e.d=function(n,t,r)&#123;e.o(n,t)||Object.defineProperty(n,t,&#123;enumerable:!0,get:r&#125;)&#125;,e.r=function(n)&#123;&quot;undefined&quot;!=typeof Symbol&amp;&amp;Symbol.toStringTag&amp;&amp;Object.defineProperty(n,Symbol.toStringTag,&#123;value:&quot;Module&quot;&#125;),Object.defineProperty(n,&quot;__esModule&quot;,&#123;value:!0&#125;)&#125;,e.t=function(n,t)&#123;if(1&amp;t&amp;&amp;(n=e(n)),8&amp;t)return n;if(4&amp;t&amp;&amp;&quot;object&quot;==typeof n&amp;&amp;n&amp;&amp;n.__esModule)return n;var r=Object.create(null);if(e.r(r),Object.defineProperty(r,&quot;default&quot;,&#123;enumerable:!0,value:n&#125;),2&amp;t&amp;&amp;&quot;string&quot;!=typeof n)for(var o in n)e.d(r,o,function(t)&#123;return n[t]&#125;.bind(null,o));return r&#125;,e.n=function(n)&#123;var t=n&amp;&amp;n.__esModule?function()&#123;return n.default&#125;:function()&#123;return n&#125;;return e.d(t,&quot;a&quot;,t),t&#125;,e.o=function(n,t)&#123;return Object.prototype.hasOwnProperty.call(n,t)&#125;,e.p=&quot;&quot;,e(e.s=0)&#125;([function(n,t,e)&#123;var r=e(1),o=e(2),u=e(3);o(&quot;大家好,我的名字是&quot;+r),console.log(u.add(2,3))&#125;,function(n,t)&#123;n.exports=&quot;小明&quot;&#125;,function(n,t)&#123;n.exports=function(n)&#123;console.log(n)&#125;&#125;,function(n,t,e)&#123;&quot;use strict&quot;;function r(n)&#123;return n*n&#125;function o(n)&#123;return n*n*n&#125;function u(n,t)&#123;return n+t&#125;function c(n,t)&#123;return n-t&#125;e.r(t),</span><br><span class="line">e.d(t,&quot;square&quot;,(function()&#123;return r&#125;)),</span><br><span class="line">e.d(t,&quot;cube&quot;,(function()&#123;return o&#125;)),</span><br><span class="line">e.d(t,&quot;add&quot;,(function()&#123;return u&#125;)),</span><br><span class="line">e.d(t,&quot;cut&quot;,(function()&#123;return c&#125;))&#125;]);</span><br></pre></td></tr></table></figure></p><p>可以看出，我们只使用了<code>math.js</code>中的<code>add</code>方法，但是打包后的内容里<code>math.js</code>中导出的<code>square</code>、<code>cube</code>、<code>add</code>、<code>cut</code>方法都被打包了，这显然不是我们想要的结果。</p><p>我们修改<code>package.json</code>的内容</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">    &#123;</span><br><span class="line">      &quot;dependencies&quot;: &#123;</span><br><span class="line">        &quot;babel-loader&quot;: &quot;^8.0.6&quot;,</span><br><span class="line">        &quot;copy-webpack-plugin&quot;: &quot;^5.1.1&quot;,</span><br><span class="line">        &quot;webpack&quot;: &quot;^4.41.5&quot;,</span><br><span class="line">        &quot;webpack-cli&quot;: &quot;^3.3.10&quot;,</span><br><span class="line">        &quot;webpack-dev-server&quot;: &quot;^3.10.1&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;name&quot;: &quot;webpack_learn&quot;,</span><br><span class="line">      &quot;version&quot;: &quot;1.0.0&quot;,</span><br><span class="line">      &quot;main&quot;: &quot;index.js&quot;,</span><br><span class="line">      &quot;devDependencies&quot;: &#123;</span><br><span class="line">        &quot;@babel/core&quot;: &quot;^7.7.7&quot;,</span><br><span class="line">        &quot;@babel/preset-env&quot;: &quot;^7.7.7&quot;,</span><br><span class="line">        &quot;babel-core&quot;: &quot;^6.26.3&quot;,</span><br><span class="line">        &quot;babel-preset-env&quot;: &quot;^1.7.0&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;scripts&quot;: &#123;</span><br><span class="line">        &quot;build&quot;: &quot;webpack&quot;,</span><br><span class="line">        &quot;watch&quot;: &quot;webpack --watch&quot;,</span><br><span class="line">        &quot;serve&quot;: &quot;webpack-dev-server --open&quot;,</span><br><span class="line">        &quot;dev&quot;: &quot;webpack --mode development&quot;,</span><br><span class="line">        &quot;product&quot;: &quot;webpack --mode production&quot;,</span><br><span class="line">        &quot;testParams&quot;: &quot;webpack --mode production --env.production product --param1 1 --param2 2 --explane 这是一个说明&quot;,</span><br><span class="line">        &quot;showColorAndProgress&quot;: &quot;webpack --progress --colors&quot;,</span><br><span class="line">        &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;author&quot;: &quot;&quot;,</span><br><span class="line">+     &quot;sideEffects&quot;: false,</span><br><span class="line">      &quot;license&quot;: &quot;ISC&quot;,</span><br><span class="line">      &quot;description&quot;: &quot;&quot;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>然后执行打包指令<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build #也可以yarn build</span><br></pre></td></tr></table></figure></p><p>然后我们发现，打包指令中，依然包含<code>math.js</code>导出的四个方法</p><p>修改<code>index.js</code>文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">    let name = require(&apos;./let.js&apos;);</span><br><span class="line">    let sayName = require(&apos;./get.js&apos;);</span><br><span class="line">-   let math = require(&apos;./math.js&apos;);</span><br><span class="line">+   import &#123;add&#125; from &apos;./math.js&apos;</span><br><span class="line">    sayName(&apos;大家好,我的名字是&apos;+name)</span><br><span class="line">-   console.log(math.add(2,3))</span><br><span class="line">-   console.log(math.add(9,18))</span><br><span class="line"></span><br><span class="line">+   console.log(add(2,3))</span><br><span class="line">+   console.log(add(9,18))</span><br></pre></td></tr></table></figure><p>修改<code>webpack.config.js</code>文件增加<code>mode:&quot;production&quot;</code></p><p>再次打包</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br></pre></td><td class="code"><pre><span class="line">!function(e) &#123;</span><br><span class="line">    var t = &#123;&#125;;</span><br><span class="line">    function n(r) &#123;</span><br><span class="line">        if (t[r])</span><br><span class="line">            return t[r].exports;</span><br><span class="line">        var o = t[r] = &#123;</span><br><span class="line">            i: r,</span><br><span class="line">            l: !1,</span><br><span class="line">            exports: &#123;&#125;</span><br><span class="line">        &#125;;</span><br><span class="line">        return e[r].call(o.exports, o, o.exports, n),</span><br><span class="line">        o.l = !0,</span><br><span class="line">        o.exports</span><br><span class="line">    &#125;</span><br><span class="line">    n.m = e,</span><br><span class="line">    n.c = t,</span><br><span class="line">    n.d = function(e, t, r) &#123;</span><br><span class="line">        n.o(e, t) || Object.defineProperty(e, t, &#123;</span><br><span class="line">            enumerable: !0,</span><br><span class="line">            get: r</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    ,</span><br><span class="line">    n.r = function(e) &#123;</span><br><span class="line">        &quot;undefined&quot; != typeof Symbol &amp;&amp; Symbol.toStringTag &amp;&amp; Object.defineProperty(e, Symbol.toStringTag, &#123;</span><br><span class="line">            value: &quot;Module&quot;</span><br><span class="line">        &#125;),</span><br><span class="line">        Object.defineProperty(e, &quot;__esModule&quot;, &#123;</span><br><span class="line">            value: !0</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">    ,</span><br><span class="line">    n.t = function(e, t) &#123;</span><br><span class="line">        if (1 &amp; t &amp;&amp; (e = n(e)),</span><br><span class="line">        8 &amp; t)</span><br><span class="line">            return e;</span><br><span class="line">        if (4 &amp; t &amp;&amp; &quot;object&quot; == typeof e &amp;&amp; e &amp;&amp; e.__esModule)</span><br><span class="line">            return e;</span><br><span class="line">        var r = Object.create(null);</span><br><span class="line">        if (n.r(r),</span><br><span class="line">        Object.defineProperty(r, &quot;default&quot;, &#123;</span><br><span class="line">            enumerable: !0,</span><br><span class="line">            value: e</span><br><span class="line">        &#125;),</span><br><span class="line">        2 &amp; t &amp;&amp; &quot;string&quot; != typeof e)</span><br><span class="line">            for (var o in e)</span><br><span class="line">                n.d(r, o, function(t) &#123;</span><br><span class="line">                    return e[t]</span><br><span class="line">                &#125;</span><br><span class="line">                .bind(null, o));</span><br><span class="line">        return r</span><br><span class="line">    &#125;</span><br><span class="line">    ,</span><br><span class="line">    n.n = function(e) &#123;</span><br><span class="line">        var t = e &amp;&amp; e.__esModule ? function() &#123;</span><br><span class="line">            return e.default</span><br><span class="line">        &#125;</span><br><span class="line">        : function() &#123;</span><br><span class="line">            return e</span><br><span class="line">        &#125;</span><br><span class="line">        ;</span><br><span class="line">        return n.d(t, &quot;a&quot;, t),</span><br><span class="line">        t</span><br><span class="line">    &#125;</span><br><span class="line">    ,</span><br><span class="line">    n.o = function(e, t) &#123;</span><br><span class="line">        return Object.prototype.hasOwnProperty.call(e, t)</span><br><span class="line">    &#125;</span><br><span class="line">    ,</span><br><span class="line">    n.p = &quot;&quot;,</span><br><span class="line">    n(n.s = 2)</span><br><span class="line">&#125;([function(e, t) &#123;</span><br><span class="line">    e.exports = &quot;小明&quot;</span><br><span class="line">&#125;</span><br><span class="line">, function(e, t) &#123;</span><br><span class="line">    e.exports = function(e) &#123;</span><br><span class="line">        console.log(e)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">, function(e, t, n) &#123;</span><br><span class="line">    &quot;use strict&quot;;</span><br><span class="line">    function r(e, t) &#123;</span><br><span class="line">        return e + t</span><br><span class="line">    &#125;</span><br><span class="line">    n.r(t);</span><br><span class="line">    var o = n(0);</span><br><span class="line">    n(1)(&quot;大家好,我的名字是&quot; + o),</span><br><span class="line">    console.log(r(2, 3)),</span><br><span class="line">    console.log(r(9, 18))</span><br><span class="line">&#125;</span><br><span class="line">]);</span><br></pre></td></tr></table></figure><p>最后的结果，可以看出，add方法被打包成了</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function r(e, t) &#123;</span><br><span class="line">return e + t</span><br><span class="line">&#125;</span><br><span class="line">n.r(t);</span><br></pre></td></tr></table></figure><p>而其他的方法并没有被打包进来，实现了代码的裁剪，根据表现来看，如果你希望使用<code>webpack</code>的<code>tree-shaking</code>的话，需要如下使用</p><ol><li>js文件中，每一个方法，都需要使用<code>exports</code>导出，使用方法的地方，使用<code>impoet {xxx} from &#39;xx/xx&#39;</code>来按需导入，使用<code>require</code>是无法完成按需导入的</li><li><code>package.json</code>中，增加<code>&quot;sideEffects&quot;: false</code>声明文档安全性是否拥有副作用，</li><li><code>config.webpack.js</code>中，增加<code>mode:production</code>或者使用<code>webpack</code>的<code>UglifyJSPlugin</code>插件</li></ol>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;由于，我们在开发过程中，会引入很多大大小小的模块，比如一个计算方法通用的大包，封装了很多很多的方法，但是我们只用到了其中一两个方法，往往希望
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="javascript" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
    
      <category term="javascript" scheme="http://www.meixiaohan.com/tags/javascript/"/>
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/tags/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/tags/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
      <category term="摇树优化" scheme="http://www.meixiaohan.com/tags/%E6%91%87%E6%A0%91%E4%BC%98%E5%8C%96/"/>
    
      <category term="tree-shaking" scheme="http://www.meixiaohan.com/tags/tree-shaking/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记10-热更新</title>
    <link href="http://www.meixiaohan.com/2019/08/27/webpack_learn_10/"/>
    <id>http://www.meixiaohan.com/2019/08/27/webpack_learn_10/</id>
    <published>2019-08-26T16:00:00.000Z</published>
    <updated>2020-01-15T09:50:19.495Z</updated>
    
    <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>在上一节中，已经能够生成一个能够自动重新编译本地服务器了，但是，有一个问题，在项目写的比较大的时候，每次打包的时间就会变得很长，为了解决这个问题，webpack也支持使用模块热替换的方式来进行差异修改，也就是热更新，可以在每次修改的时候，只重新刷新修改的那一部分，这样刷新的速度就会变得很快了。</p><h1 id="方案"><a href="#方案" class="headerlink" title="方案"></a>方案</h1><p>webpack为这种情况，提供了插件</p><ol><li><code>HotModuleReplacementPlugin</code>启用热模块更换，也称为HMR</li><li><code>NamedModulesPlugin</code>该插件会显示模块的相对路径</li></ol><h1 id="写法"><a href="#写法" class="headerlink" title="写法"></a>写法</h1><h2 id="修改config-webpack-js"><a href="#修改config-webpack-js" class="headerlink" title="修改config.webpack.js"></a>修改config.webpack.js</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">    //config.webpack.js</span><br><span class="line">    const path = require(&apos;path&apos;)</span><br><span class="line">    const CopyWebpackPlugin = require(&apos;copy-webpack-plugin&apos;)</span><br><span class="line">+   const webpack = require(&apos;webpack&apos;);</span><br><span class="line">    module.exports = &#123;</span><br><span class="line">        //配置函数接受两个参数env和argv</span><br><span class="line">        //env:环境对象</span><br><span class="line">        //Webpack-CLI 的命令行选项</span><br><span class="line">        entry: &apos;./src/index.js&apos;, //设置默认</span><br><span class="line">        output: &#123;</span><br><span class="line">            ...,</span><br><span class="line">        &#125;,</span><br><span class="line">        devtool: &apos;inline-source-map&apos;,</span><br><span class="line">        module: &#123;</span><br><span class="line">            ...,</span><br><span class="line">        &#125;,</span><br><span class="line">        devServer: &#123;</span><br><span class="line">            contentBase: &apos;./dist&apos;,</span><br><span class="line">+           hot: true</span><br><span class="line">        &#125;,</span><br><span class="line">        plugins: [</span><br><span class="line">            new CopyWebpackPlugin([</span><br><span class="line">                &#123;</span><br><span class="line">                    from: path.join(__dirname, &apos;/staticFrom/&apos;),</span><br><span class="line">                    to: path.join(__dirname+&apos;/dist/&apos;)</span><br><span class="line">                &#125;</span><br><span class="line">            ]),</span><br><span class="line">+         new webpack.NamedModulesPlugin(),</span><br><span class="line">+         new webpack.HotModuleReplacementPlugin()        </span><br><span class="line">        ]</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>然后修改<code>package.json</code>中的<code>script</code><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">    //package.json</span><br><span class="line">    &#123;</span><br><span class="line">      &quot;dependencies&quot;: &#123;</span><br><span class="line">        &quot;babel-loader&quot;: &quot;^8.0.6&quot;,</span><br><span class="line">        &quot;copy-webpack-plugin&quot;: &quot;^5.1.1&quot;,</span><br><span class="line">        &quot;webpack&quot;: &quot;^4.41.5&quot;,</span><br><span class="line">        &quot;webpack-cli&quot;: &quot;^3.3.10&quot;,</span><br><span class="line">        &quot;webpack-dev-server&quot;: &quot;^3.10.1&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;name&quot;: &quot;webpack_learn&quot;,</span><br><span class="line">      &quot;version&quot;: &quot;1.0.0&quot;,</span><br><span class="line">      &quot;main&quot;: &quot;index.js&quot;,</span><br><span class="line">      &quot;devDependencies&quot;: &#123;</span><br><span class="line">        &quot;@babel/core&quot;: &quot;^7.7.7&quot;,</span><br><span class="line">        &quot;@babel/preset-env&quot;: &quot;^7.7.7&quot;,</span><br><span class="line">        &quot;babel-core&quot;: &quot;^6.26.3&quot;,</span><br><span class="line">        &quot;babel-preset-env&quot;: &quot;^1.7.0&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;scripts&quot;: &#123;</span><br><span class="line">        &quot;build&quot;: &quot;webpack&quot;,</span><br><span class="line">        &quot;watch&quot;: &quot;webpack --watch&quot;,</span><br><span class="line">-       &quot;serve&quot;: &quot;webpack-dev-server --open&quot;,</span><br><span class="line">+       &quot;serve&quot;: &quot;webpack-dev-server --hotOnly&quot;,</span><br><span class="line">        &quot;dev&quot;: &quot;webpack --mode development&quot;,</span><br><span class="line">        &quot;product&quot;: &quot;webpack --mode production&quot;,</span><br><span class="line">        &quot;testParams&quot;: &quot;webpack --mode production --env.production product --param1 1 --param2 2 --explane 这是一个说明&quot;,</span><br><span class="line">        &quot;showColorAndProgress&quot;: &quot;webpack --progress --colors&quot;,</span><br><span class="line">        &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;author&quot;: &quot;&quot;,</span><br><span class="line">      &quot;license&quot;: &quot;ISC&quot;,</span><br><span class="line">      &quot;description&quot;: &quot;&quot;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></p><p>然后在命令行中执行<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run serve #也可以yarn watch</span><br></pre></td></tr></table></figure></p><p>此时，就是模块热更新的开发状态啦</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;在上一节中，已经能够生成一个能够自动重新编译本地服务器了，但是，有一个问题，在项目写的比较大的时候，每次打包的时间就会变得很长，为了解决这个
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="javascript" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
    
      <category term="javascript" scheme="http://www.meixiaohan.com/tags/javascript/"/>
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/tags/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/tags/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记9-建立开发环境</title>
    <link href="http://www.meixiaohan.com/2019/08/23/webpack_learn_9/"/>
    <id>http://www.meixiaohan.com/2019/08/23/webpack_learn_9/</id>
    <published>2019-08-22T16:00:00.000Z</published>
    <updated>2020-01-20T06:06:22.122Z</updated>
    
    <content type="html"><![CDATA[<h1 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h1><p>在我们的开发中，很多的代码会频繁的变动，如果每次改动都使用<code>npm run build</code>来打包的话，是一件效率很低的事情，而且这个服务，一般来说，打包的时候，才需要使用，因此需要一个本地服务的，可以快捷的看到打包后的内容</p><h1 id="方案"><a href="#方案" class="headerlink" title="方案"></a>方案</h1><p>webpack为这种情况，提供了观察者模式，在每次文件发生变动的时候，自动执行编译，就不用每次都<code>npm run build</code>来打包了</p><h1 id="写法"><a href="#写法" class="headerlink" title="写法"></a>写法</h1><h2 id="watch-自动编译修改的文件"><a href="#watch-自动编译修改的文件" class="headerlink" title="watch 自动编译修改的文件"></a>watch 自动编译修改的文件</h2><p>我们可以在<code>scripts</code>中，新加一条命令<code>webpack --watch</code>来启动观察者模式<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">//package.json</span><br><span class="line">&#123;</span><br><span class="line">  &quot;dependencies&quot;: &#123;</span><br><span class="line">    &quot;babel-loader&quot;: &quot;^8.0.6&quot;,</span><br><span class="line">    &quot;copy-webpack-plugin&quot;: &quot;^5.1.1&quot;,</span><br><span class="line">    &quot;webpack&quot;: &quot;^4.41.5&quot;,</span><br><span class="line">    &quot;webpack-cli&quot;: &quot;^3.3.10&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;name&quot;: &quot;webpack_learn&quot;,</span><br><span class="line">  &quot;version&quot;: &quot;1.0.0&quot;,</span><br><span class="line">  &quot;main&quot;: &quot;index.js&quot;,</span><br><span class="line">  &quot;devDependencies&quot;: &#123;</span><br><span class="line">    &quot;@babel/core&quot;: &quot;^7.7.7&quot;,</span><br><span class="line">    &quot;@babel/preset-env&quot;: &quot;^7.7.7&quot;,</span><br><span class="line">    &quot;babel-core&quot;: &quot;^6.26.3&quot;,</span><br><span class="line">    &quot;babel-preset-env&quot;: &quot;^1.7.0&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;scripts&quot;: &#123;</span><br><span class="line">    &quot;build&quot;: &quot;webpack&quot;,</span><br><span class="line">+   &quot;watch&quot;: &quot;webpack --watch&quot;,</span><br><span class="line">    &quot;dev&quot;: &quot;webpack --mode development&quot;,</span><br><span class="line">    &quot;product&quot;: &quot;webpack --mode production&quot;,</span><br><span class="line">    &quot;testParams&quot;: &quot;webpack --mode production --env.production product --param1 1 --param2 2 --explane 这是一个说明&quot;,</span><br><span class="line">    &quot;showColorAndProgress&quot;: &quot;webpack --progress --colors&quot;,</span><br><span class="line">    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">  &quot;author&quot;: &quot;&quot;,</span><br><span class="line">  &quot;license&quot;: &quot;ISC&quot;,</span><br><span class="line">  &quot;description&quot;: &quot;&quot;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>然后在命令行中执行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run watch #也可以yarn watch</span><br></pre></td></tr></table></figure><p>然后我们在浏览器中，打开刚才的文件，并且查看控制台，控制台中打印了<code>大家好,我的名字是小明</code>，然后我们修改一下<code>/src/let.js</code>,及<code>index.html</code>文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">    //let.js</span><br><span class="line">-   let name = &apos;小明&apos;;</span><br><span class="line">+   let name = &apos;小刚;</span><br><span class="line">    module.exports = name;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    //index.html</span><br><span class="line">    &lt;!DOCTYPE html&gt;</span><br><span class="line">    &lt;html&gt;</span><br><span class="line">        &lt;head&gt;</span><br><span class="line">            &lt;meta charset=&quot;utf-8&quot;&gt;</span><br><span class="line">            &lt;title&gt;&lt;/title&gt;</span><br><span class="line">        &lt;/head&gt;</span><br><span class="line">        &lt;body&gt;</span><br><span class="line">-           &lt;script src=&quot;./main.js&quot; type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;</span><br><span class="line">+           &lt;script src=&quot;./bundle.js&quot; type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;</span><br><span class="line">        &lt;/body&gt;</span><br><span class="line">    &lt;/html&gt;</span><br></pre></td></tr></table></figure><p>然后保存文件，然后在刚打开的浏览器里，刷新页面，然后控制台中，变成了<code>大家好,我的名字是小刚</code>。这样，每次修改就不用执行打包指令了</p><h2 id="sourceMap-查找报错所在"><a href="#sourceMap-查找报错所在" class="headerlink" title="sourceMap 查找报错所在"></a>sourceMap 查找报错所在</h2><p>开发中，最重要的一个环节，就是代码的调试，如果我们在写的代码中，出现了报错，希望很快的知道是哪里的报错，但是在webpack中，代码经过层层的模块打包，合并成了最后的一个js文件，里面的内容是编译后的内容，</p><p>我们尝试一下报错，将刚刚的<code>get.js</code>中，加一个报错信息。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">    //get.js</span><br><span class="line">module.exports = function(name)&#123;</span><br><span class="line">console.log(name)</span><br><span class="line">+       throw new Error(&apos;这里有个报错&apos;)</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">bundle.js:1 Uncaught Error: 这里有个报错</span><br><span class="line">    at e.exports (bundle.js:1)</span><br><span class="line">    at Object.&lt;anonymous&gt; (bundle.js:1)</span><br><span class="line">    at n (bundle.js:1)</span><br><span class="line">    at bundle.js:1</span><br><span class="line">    at bundle.js:1</span><br></pre></td></tr></table></figure><p>报错信息指向了<code>bundle.js</code>打包后的文件，这显然不是我们想要的</p><p>这个时候，我们可以使用<code>sourceMap</code>来解决这个问题。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">//webpack.config.js</span><br><span class="line">module.exports = &#123;</span><br><span class="line">    entry:&#123;</span><br><span class="line">        ...</span><br><span class="line">    &#125;,</span><br><span class="line">    output:&#123;</span><br><span class="line">        ...</span><br><span class="line">    &#125;,</span><br><span class="line">+   devtool: &apos;inline-source-map&apos;,</span><br><span class="line">    module:&#123;&#125;,</span><br><span class="line">    plugins:&#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后重新执行<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run watch</span><br></pre></td></tr></table></figure></p><p>这样，控制台的报错就变成了<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">get.js:3 Uncaught Error: 这里有个报错</span><br><span class="line">    at e.exports (get.js:3)</span><br><span class="line">    at Object.&lt;anonymous&gt; (index.js:4)</span><br><span class="line">    at n (bootstrap:19)</span><br><span class="line">    at bootstrap:83</span><br><span class="line">    at bundle.js:1</span><br></pre></td></tr></table></figure></p><p>指向了正确的位置，我们复原代码，进行下一步尝试<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">    //get.js</span><br><span class="line">module.exports = function(name)&#123;</span><br><span class="line">console.log(name)</span><br><span class="line">-       throw new Error(&apos;这里有个报错&apos;)</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></p><h2 id="webpack-dev-server-自动刷新页面"><a href="#webpack-dev-server-自动刷新页面" class="headerlink" title="webpack-dev-server 自动刷新页面"></a>webpack-dev-server 自动刷新页面</h2><p>前面讲述了观察者模式及报错位置查找，但是美中不足的是，我们每次需要手动刷新来观察变化，这种情况下，可以使用<code>webpack</code>中的的<code>webpack-dev-server</code>模块，来完成自动更新的行为</p><p>首先安装<code>webpack-dev-server</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install webpack-dev-server #或者yarn add webpack-dev-server</span><br></pre></td></tr></table></figure><p>安装完毕后，修改一下<code>webpack.config.js</code>文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">    const path = require(&apos;path&apos;)</span><br><span class="line">    const CopyWebpackPlugin = require(&apos;copy-webpack-plugin&apos;)</span><br><span class="line">    </span><br><span class="line">    module.exports = &#123;</span><br><span class="line">        //配置函数接受两个参数env和argv</span><br><span class="line">        //env:环境对象</span><br><span class="line">        //Webpack-CLI 的命令行选项</span><br><span class="line">        entry: &apos;./src/index.js&apos;, //设置默认</span><br><span class="line">        output: &#123;</span><br><span class="line">            filename: &apos;bundle.js&apos;,</span><br><span class="line">            path: path.resolve(__dirname, &apos;dist&apos;)</span><br><span class="line">        &#125;,</span><br><span class="line">devtool: &apos;inline-source-map&apos;,</span><br><span class="line">+       devServer: &#123;</span><br><span class="line">+           contentBase: &apos;./dist&apos;</span><br><span class="line">+       &#125;,</span><br><span class="line">        module: &#123;</span><br><span class="line">            rules: [&#123;</span><br><span class="line">                //里面为匹配的规则</span><br><span class="line">                test: /\.m?js$/,</span><br><span class="line">                exclude: /(node_modules|bower_components)/,</span><br><span class="line">                use: &#123;</span><br><span class="line">                    loader: &apos;babel-loader&apos;,</span><br><span class="line">                    options: &#123;</span><br><span class="line">                        presets: [&apos;@babel/preset-env&apos;]</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;]</span><br><span class="line">        &#125;,</span><br><span class="line">        plugins: [</span><br><span class="line">            new CopyWebpackPlugin([</span><br><span class="line">                &#123;</span><br><span class="line">                    from: path.join(__dirname, &apos;/staticFrom/&apos;),</span><br><span class="line">                    to: path.join(__dirname+&apos;/dist/&apos;)</span><br><span class="line">                &#125;</span><br><span class="line">            ])</span><br><span class="line">        ]</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>声明开发服务，并将 <code>dist</code> 目录下的文件，作为可访问文件，并且修改<code>package.json</code>中声明一条</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">    &#123;</span><br><span class="line">        ...,</span><br><span class="line">        &quot;scripts&quot;:&#123;</span><br><span class="line">            ...,</span><br><span class="line">+           &quot;serve&quot;: &quot;webpack-dev-server --open&quot;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>然后执行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run serve # 或者yarn serve</span><br></pre></td></tr></table></figure><p>执行完毕后，浏览器自动打开了一个地址为<code>localhost:8080</code>的网页，打开控制台，可以看到我们刚刚写入的<code>大家好,我的名字是小刚</code>，然后我们继续把小刚，改回刚才的小明</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">    //let.js</span><br><span class="line">-   let name = &apos;小刚;</span><br><span class="line">+   let name = &apos;小明&apos;;</span><br><span class="line">    module.exports = name;</span><br></pre></td></tr></table></figure><p>然后保存，浏览器的控制台，自动的就变化成了<code>大家好,我的名字是小明</code>；</p><p>这样就建立了一个开发用的服务器，且每次修改，都会重新编译。</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h1 id=&quot;背景&quot;&gt;&lt;a href=&quot;#背景&quot; class=&quot;headerlink&quot; title=&quot;背景&quot;&gt;&lt;/a&gt;背景&lt;/h1&gt;&lt;p&gt;在我们的开发中，很多的代码会频繁的变动，如果每次改动都使用&lt;code&gt;npm run build&lt;/code&gt;来打包的话，是一件效率很低的事
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="javascript" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
    
      <category term="javascript" scheme="http://www.meixiaohan.com/tags/javascript/"/>
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/tags/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/tags/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记8-名词解释</title>
    <link href="http://www.meixiaohan.com/2019/08/19/webpack_learn_8/"/>
    <id>http://www.meixiaohan.com/2019/08/19/webpack_learn_8/</id>
    <published>2019-08-18T16:00:00.000Z</published>
    <updated>2020-01-15T02:13:09.606Z</updated>
    
    <content type="html"><![CDATA[<p>之前已经简单的了解了<code>webpack</code>中<code>配置文件</code>、<code>loader</code>、<code>插件</code>、<code>如何安装</code>了</p><p>这里统一加一个名词解释</p><h2 id="名词解释"><a href="#名词解释" class="headerlink" title="名词解释"></a>名词解释</h2><table><thead><tr><th style="text-align:center">参数</th><th style="text-align:center">说明</th><th style="text-align:center">备注</th></tr></thead><tbody><tr><td style="text-align:center">mode</td><td style="text-align:center">项目环境</td><td style="text-align:center">webpack4.0中出的模式概念，可以传入development(开发环境)/production(生产环境)，理解为可以通过不同的config文件来分别配置生产与测试环境</td><td></td></tr><tr><td style="text-align:center">entry</td><td style="text-align:center">项目入口</td><td style="text-align:center">webpack开始打包的入口文件，打包这个文件里，引用的其他包，及引入的包所再次引入的包，每个html文档只使用一个依赖图，也就是entry</td><td></td></tr><tr><td style="text-align:center">output</td><td style="text-align:center">项目出口</td><td style="text-align:center">webpack打包完成后，输出的文件，可以使用webpack占位符<a href="#占位符">占位符</a></td><td></td></tr><tr><td style="text-align:center">module</td><td style="text-align:center">开发中每一个文件都可以看做 module，模块不局限于 js，也包含 css、图片等</td><td style="text-align:center">使校验、调试、测试、扩展、复用都轻而易举 例如：<a href="#什么是模块">什么是模块</a></td><td></td></tr><tr><td style="text-align:center">loader</td><td style="text-align:center">模块转化器，模块的处理器，对模块进行转换处理</td><td style="text-align:center">提供了处理前端构建步骤的强大方法，如将额外的语言<code>typescript</code>转化为<code>javascript</code>，将<code>图片</code>转换为<code>base64格式</code>来减少一次请求等  <a href="#loader使用方式">loader使用方式</a></td><td></td></tr><tr><td style="text-align:center">plugin</td><td style="text-align:center">扩展插件，插件可以处理 chunk，也可以对最后的打包结果进行处理，可以完成 loader 完不成的任务</td><td style="text-align:center">插件是 webpack 的支柱功能,由于插件可以携带参数/选项，你必须在 <code>webpack</code> 配置中，向 <code>plugins</code> 属性传入 <code>new</code> 实例。</td><td></td></tr><tr><td style="text-align:center">context</td><td style="text-align:center">上下文，也是基础目录，绝对路径，用于从配置中解析入口起点(entry point)和 loader</td><td style="text-align:center">默认值为path.resolve(__dirname, “app”)，也就是当前路径 <a href="#如何修改context">如何修改context</a></td><td></td></tr></tbody></table><h2 id="webpack占位符"><a href="#webpack占位符" class="headerlink" title="webpack占位符"></a><a id="占位符">webpack占位符</a></h2><table><thead><tr><th style="text-align:center">模板</th><th style="text-align:center">描述</th></tr></thead><tbody><tr><td style="text-align:center">[hash]</td><td style="text-align:center">模块标识符(module identifier)的 hash</td><td></td></tr><tr><td style="text-align:center">[chunkhash]</td><td style="text-align:center">chunk 内容的 hash</td><td></td></tr><tr><td style="text-align:center">[name]</td><td style="text-align:center">模块名称</td><td></td></tr><tr><td style="text-align:center">[id]</td><td style="text-align:center">模块标识符(module identifier)</td><td></td></tr><tr><td style="text-align:center">[query]</td><td style="text-align:center">模块的 query，例如，文件名 ? 后面的字符串</td><td></td></tr></tbody></table><h2 id="什么是模块"><a href="#什么是模块" class="headerlink" title="什么是模块"></a><a id="模块">什么是模块</a></h2><ol><li><code>ES2015</code> 中的 <code>import</code> 语句</li><li><code>CommonJS</code> 中的 <code>require()</code> 语句</li><li><code>AMD</code> <code>define</code> 和 <code>require</code> 语句</li><li><code>css/sass/less</code> 文件中的 <code>@import</code> 语句。</li><li>样式(<code>url(...)</code>)或 HTML 文件(<code>&lt;img src=...&gt;</code>)中的图片链接(image url)</li></ol><h2 id="loader使用方式"><a href="#loader使用方式" class="headerlink" title="loader使用方式"></a><a id="loader使用方式">loader使用方式</a></h2><ol><li>配置（推荐）：在 webpack.config.js 文件中指定 loader，这样在维护的时候，只需要查找这一个文件即可。</li><li>内联：在每个 import 语句中显式指定 loader。</li><li>CLI：在 shell 命令中指定它们。</li></ol><h2 id="如何修改context"><a href="#如何修改context" class="headerlink" title="如何修改context"></a><a id="如何修改context">如何修改context</a></h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">// webpack.config.js</span><br><span class="line">module.exports = &#123;</span><br><span class="line">    context: &apos;一个绝对路径&apos;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>备注：context是一切打包的相对地址，所以这个值，一定要填写一个绝对地址，默认为当前目录</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;之前已经简单的了解了&lt;code&gt;webpack&lt;/code&gt;中&lt;code&gt;配置文件&lt;/code&gt;、&lt;code&gt;loader&lt;/code&gt;、&lt;code&gt;插件&lt;/code&gt;、&lt;code&gt;如何安装&lt;/code&gt;了&lt;/p&gt;
&lt;p&gt;这里统一加一个名词解释&lt;/p&gt;
&lt;h2 id=&quot;名词
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="javascript" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
    
      <category term="javascript" scheme="http://www.meixiaohan.com/tags/javascript/"/>
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/tags/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/tags/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记7-插件</title>
    <link href="http://www.meixiaohan.com/2019/08/15/webpack_learn_7/"/>
    <id>http://www.meixiaohan.com/2019/08/15/webpack_learn_7/</id>
    <published>2019-08-14T16:00:00.000Z</published>
    <updated>2020-01-20T06:36:27.340Z</updated>
    
    <content type="html"><![CDATA[<p>前面已经说明了，<code>webpack</code>是一个打包工具</p><p>在<code>webpack</code>中，还有个概念，叫插件<code>plugins</code></p><ol><li>loader 被用于转换某些类型的模块，而插件则可以用于执行范围更广的任务。</li><li>插件的范围包括，从打包优化和压缩，一直到重新定义环境中的变量。插件接口功能极其强大，可以用来处理各种各样的任务。</li><li>用来解决一些loaders无法处理的事情</li></ol><blockquote><p>webpack 插件是一个具有 apply 属性的 JavaScript 对象。apply 属性会被 webpack compiler 调用，并且 compiler 对象可在整个编译生命周期访问。</p></blockquote><p>例如，我们想在打包的时候，把A文件夹中的数据，放到B文件夹中，可以使用<code>copy-webpack-plugin</code>来进行文件的复制行为</p><p><a href="https://www.webpackjs.com/plugins/copy-webpack-plugin/" target="_blank" rel="noopener">copy-webpack-plugin文档</a><br>修改原来的文件目录</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">    webpack_learn</span><br><span class="line">    |- node_modules</span><br><span class="line">    |- package.json</span><br><span class="line">    |- yarn.lock</span><br><span class="line">+   |- staticFrom</span><br><span class="line">+       |- test.txt</span><br><span class="line">    |- src</span><br><span class="line">        |- let.js</span><br><span class="line">        |- get.js</span><br><span class="line">        |- index.js</span><br><span class="line">    |- dist</span><br><span class="line">        |- main.js</span><br></pre></td></tr></table></figure><p>由于使用了<code>copy-webpack-plugin</code>模块，根据<code>commonJs</code>规范，我们需要<code>require</code>这个文件,并且使用<code>npm</code>安装它</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install copy-webpack-plugin #或者yarn add copy-webpack-plugin</span><br></pre></td></tr></table></figure><p>我们将<code>config.webpack.js</code>文件修改为如下内容<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">//config.webpack.js</span><br><span class="line"></span><br><span class="line">    const path = require(&apos;path&apos;)</span><br><span class="line">+   const CopyWebpackPlugin = require(&apos;copy-webpack-plugin&apos;)</span><br><span class="line"></span><br><span class="line">    module.exports = &#123;</span><br><span class="line">        //配置函数接受两个参数env和argv</span><br><span class="line">        //env:环境对象</span><br><span class="line">        //Webpack-CLI 的命令行选项</span><br><span class="line">        entry: &apos;./src/index.js&apos;, //设置默认</span><br><span class="line">        output: &#123;</span><br><span class="line">            filename: &apos;bundle.js&apos;,</span><br><span class="line">            path: path.resolve(__dirname, &apos;dist&apos;)</span><br><span class="line">        &#125;,</span><br><span class="line">        module: &#123;</span><br><span class="line">            rules: [&#123;</span><br><span class="line">                //里面为匹配的规则</span><br><span class="line">                test: /\.m?js$/,</span><br><span class="line">                exclude: /(node_modules|bower_components)/,</span><br><span class="line">                use: &#123;</span><br><span class="line">                    loader: &apos;babel-loader&apos;,</span><br><span class="line">                    options: &#123;</span><br><span class="line">                        presets: [&apos;@babel/preset-env&apos;]</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;]</span><br><span class="line">        &#125;,</span><br><span class="line">+       plugins: [</span><br><span class="line">+           new CopyWebpackPlugin([</span><br><span class="line">+               &#123;</span><br><span class="line">+                   from: path.join(__dirname, &apos;/staticFrom/&apos;),//将staticFrom文件夹内所有文件</span><br><span class="line">+                   to: path.join(__dirname+&apos;/dist/&apos;)//复制到根目录下/dist/文件夹内</span><br><span class="line">+               &#125;</span><br><span class="line">+           ])</span><br><span class="line">+       ]</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></p><p>然后再执行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build #或者yarn build</span><br></pre></td></tr></table></figure><p>然后，打包后的文件目录，变成了</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">    webpack_learn</span><br><span class="line">    |- node_modules</span><br><span class="line">    |- package.json</span><br><span class="line">    |- yarn.lock</span><br><span class="line">    |- staticFrom</span><br><span class="line">        |- test.txt</span><br><span class="line">    |- src</span><br><span class="line">        |- let.js</span><br><span class="line">        |- get.js</span><br><span class="line">        |- index.js</span><br><span class="line">    |- dist</span><br><span class="line">        |- bundle.js</span><br><span class="line">        |- main.js</span><br><span class="line">+       |- test.txt</span><br><span class="line">        |- index.html</span><br></pre></td></tr></table></figure><p><code>test.txt</code>文件就被复制到了<code>dist</code>目录下</p><p>这样就成功的使用了<code>webpack</code>插件中的复制插件<code>copy-webpack-plugin</code></p><p>我们在每次打包的时候，如果是同名文件，则会覆盖之前的文件，但是，并没有清除，已经更改后的文件，例如<code>dist</code>目录下的<code>main.js</code><br>此时，我们可以使用<code>clean-webpack-plugin</code>插件来清理<code>dist</code>目录，但时刚才，我们的<code>index.html</code>是自己手动新建的，如果清除掉，还需要新建，为了自动化完成这个工作，有两种方案</p><ol><li>使用<code>copy-webpack-plugin</code>插件，复制一个<code>index.html</code>文件到<code>dist</code>目录，方法参考上方</li><li>使用<code>html-webpack-plugin</code>插件，每次都创建一个<code>index.html</code>文件</li></ol><p>首先我们使用<code>npm</code>安装它们</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install clean-webpack-plugin #或者yarn add clean-webpack-plugin</span><br><span class="line">npm install html-webpack-plugin #或者yarn add html-webpack-plugin</span><br></pre></td></tr></table></figure><p>然后修改<code>config.webpack.js</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">//config.webpack.js</span><br><span class="line"></span><br><span class="line">    const path = require(&apos;path&apos;)</span><br><span class="line">+   const &#123; CleanWebpackPlugin &#125; = require(&apos;copy-webpack-plugin&apos;)</span><br><span class="line">+   const HtmlWebpackPlugin = require(&apos;html-webpack-plugin&apos;);</span><br><span class="line">+   const CleanWebpackPlugin = require(&apos;clean-webpack-plugin&apos;);</span><br><span class="line"></span><br><span class="line">    module.exports = &#123;</span><br><span class="line">        //配置函数接受两个参数env和argv</span><br><span class="line">        //env:环境对象</span><br><span class="line">        //Webpack-CLI 的命令行选项</span><br><span class="line">        entry: &apos;./src/index.js&apos;, //设置默认</span><br><span class="line">        output: &#123;</span><br><span class="line">            filename: &apos;bundle.js&apos;,</span><br><span class="line">            path: path.resolve(__dirname, &apos;dist&apos;)</span><br><span class="line">        &#125;,</span><br><span class="line">        module: &#123;</span><br><span class="line">            rules: [&#123;</span><br><span class="line">                //里面为匹配的规则</span><br><span class="line">                test: /\.m?js$/,</span><br><span class="line">                exclude: /(node_modules|bower_components)/,</span><br><span class="line">                use: &#123;</span><br><span class="line">                    loader: &apos;babel-loader&apos;,</span><br><span class="line">                    options: &#123;</span><br><span class="line">                        presets: [&apos;@babel/preset-env&apos;]</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;]</span><br><span class="line">        &#125;,</span><br><span class="line">        plugins: [</span><br><span class="line">+           new CleanWebpackPlugin(),//webpack网站上的示例为new CleanWebpackPlugin([&apos;dist&apos;])，这种写法由于CleanWebpackPlugin更新导致不兼容的情况，正确写法如左方所示</span><br><span class="line">+           new HtmlWebpackPlugin(&#123;</span><br><span class="line">+                title: &apos;Output Management&apos;</span><br><span class="line">+           &#125;),</span><br><span class="line">            new CopyWebpackPlugin([</span><br><span class="line">                &#123;</span><br><span class="line">                    from: path.join(__dirname, &apos;/staticFrom/&apos;),//将staticFrom文件夹内所有文件</span><br><span class="line">                    to: path.join(__dirname+&apos;/dist/&apos;)//复制到根目录下/dist/文件夹内</span><br><span class="line">                &#125;</span><br><span class="line">            ])</span><br><span class="line">        ]</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>然后再执行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build #或者yarn build</span><br></pre></td></tr></table></figure><p>这样，<code>dist</code>目录，每次都会清理并新建<code>index.html</code>文件了</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;前面已经说明了，&lt;code&gt;webpack&lt;/code&gt;是一个打包工具&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;webpack&lt;/code&gt;中，还有个概念，叫插件&lt;code&gt;plugins&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;loader 被用于转换某些类型的模块，而插件则可以用于
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="javascript" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
    
      <category term="javascript" scheme="http://www.meixiaohan.com/tags/javascript/"/>
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/tags/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/tags/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记6-插件</title>
    <link href="http://www.meixiaohan.com/2019/08/11/webpack_learn_6/"/>
    <id>http://www.meixiaohan.com/2019/08/11/webpack_learn_6/</id>
    <published>2019-08-10T16:00:00.000Z</published>
    <updated>2020-01-13T10:29:09.649Z</updated>
    
    <content type="html"><![CDATA[<p>前面已经说明了，<code>webpack</code>是一个打包工具</p><p>在<code>webpack</code>中，还有个概念，叫插件<code>plugins</code></p><ol><li>loader 被用于转换某些类型的模块，而插件则可以用于执行范围更广的任务。</li><li>插件的范围包括，从打包优化和压缩，一直到重新定义环境中的变量。插件接口功能极其强大，可以用来处理各种各样的任务。</li><li>用来解决一些loaders无法处理的事情</li></ol><blockquote><p>webpack 插件是一个具有 apply 属性的 JavaScript 对象。apply 属性会被 webpack compiler 调用，并且 compiler 对象可在整个编译生命周期访问。</p></blockquote><p>例如，我们想在打包的时候，把A文件夹中的数据，放到B文件夹中，可以使用<code>copy-webpack-plugin</code>来进行文件的复制行为</p><p><a href="https://www.webpackjs.com/plugins/copy-webpack-plugin/" target="_blank" rel="noopener">copy-webpack-plugin文档</a><br>修改原来的文件目录</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">    webpack_learn</span><br><span class="line">    |- node_modules</span><br><span class="line">    |- package.json</span><br><span class="line">    |- yarn.lock</span><br><span class="line">+   |- staticFrom</span><br><span class="line">+       |- test.txt</span><br><span class="line">    |- src</span><br><span class="line">        |- let.js</span><br><span class="line">        |- get.js</span><br><span class="line">        |- index.js</span><br><span class="line">    |- dist</span><br><span class="line">        |- main.js</span><br></pre></td></tr></table></figure><p>由于使用了<code>copy-webpack-plugin</code>模块，根据<code>commonJs</code>规范，我们需要<code>require</code>这个文件,并且使用<code>npm</code>安装它<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install copy-webpack-plugin #或者yarn add copy-webpack-plugin</span><br></pre></td></tr></table></figure></p><p>我们将<code>config.webpack.js</code>文件修改为如下内容<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">//config.webpack.js</span><br><span class="line"></span><br><span class="line">    const path = require(&apos;path&apos;)</span><br><span class="line">+   const CopyWebpackPlugin = require(&apos;copy-webpack-plugin&apos;)</span><br><span class="line"></span><br><span class="line">    module.exports = &#123;</span><br><span class="line">        //配置函数接受两个参数env和argv</span><br><span class="line">        //env:环境对象</span><br><span class="line">        //Webpack-CLI 的命令行选项</span><br><span class="line">        entry: &apos;./src/index.js&apos;, //设置默认</span><br><span class="line">        output: &#123;</span><br><span class="line">            filename: &apos;bundle.js&apos;,</span><br><span class="line">            path: path.resolve(__dirname, &apos;dist&apos;)</span><br><span class="line">        &#125;,</span><br><span class="line">        module: &#123;</span><br><span class="line">            rules: [&#123;</span><br><span class="line">                //里面为匹配的规则</span><br><span class="line">                test: /\.m?js$/,</span><br><span class="line">                exclude: /(node_modules|bower_components)/,</span><br><span class="line">                use: &#123;</span><br><span class="line">                    loader: &apos;babel-loader&apos;,</span><br><span class="line">                    options: &#123;</span><br><span class="line">                        presets: [&apos;@babel/preset-env&apos;]</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;]</span><br><span class="line">        &#125;,</span><br><span class="line">+       plugins: [</span><br><span class="line">+           new CopyWebpackPlugin([</span><br><span class="line">+               &#123;</span><br><span class="line">+                   from: path.join(__dirname, &apos;/staticFrom/&apos;),//将staticFrom文件夹内所有文件</span><br><span class="line">+                   to: path.join(__dirname+&apos;/dist/&apos;)//复制到根目录下/dist/文件夹内</span><br><span class="line">+               &#125;</span><br><span class="line">+           ])</span><br><span class="line">+       ]</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></p><p>然后再执行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build #或者yarn build</span><br></pre></td></tr></table></figure><p>然后，打包后的文件目录，变成了</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">    webpack_learn</span><br><span class="line">    |- node_modules</span><br><span class="line">    |- package.json</span><br><span class="line">    |- yarn.lock</span><br><span class="line">    |- staticFrom</span><br><span class="line">        |- test.txt</span><br><span class="line">    |- src</span><br><span class="line">        |- let.js</span><br><span class="line">        |- get.js</span><br><span class="line">        |- index.js</span><br><span class="line">    |- dist</span><br><span class="line">        |- bundle.js</span><br><span class="line">        |- main.js</span><br><span class="line">+       |- test.txt</span><br><span class="line">        |- index.html</span><br></pre></td></tr></table></figure><p><code>test.txt</code>文件就被复制到了<code>dist</code>目录下</p><p>这样就成功的使用了<code>webpack</code>插件中的复制插件<code>copy-webpack-plugin</code></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;前面已经说明了，&lt;code&gt;webpack&lt;/code&gt;是一个打包工具&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;webpack&lt;/code&gt;中，还有个概念，叫插件&lt;code&gt;plugins&lt;/code&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;loader 被用于转换某些类型的模块，而插件则可以用于
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="javascript" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
    
      <category term="javascript" scheme="http://www.meixiaohan.com/tags/javascript/"/>
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/tags/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/tags/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记4-使用配置文件</title>
    <link href="http://www.meixiaohan.com/2019/08/08/webpack_learn_4/"/>
    <id>http://www.meixiaohan.com/2019/08/08/webpack_learn_4/</id>
    <published>2019-08-07T16:00:00.000Z</published>
    <updated>2020-01-13T10:30:05.391Z</updated>
    
    <content type="html"><![CDATA[<p><code>webpack</code>可以使用配置文件，也就是名为<code>webpack.config.js</code>的文件，<code>webpack.config.js</code>也是遵循<code>CommonJS规范</code>的</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">webpack_learn</span><br><span class="line">|- node_modules</span><br><span class="line">|- package.json</span><br><span class="line">|- yarn.lock</span><br><span class="line">|- webpack.config.js</span><br><span class="line">|- src</span><br><span class="line">    |- let.js</span><br><span class="line">    |- get.js</span><br><span class="line">    |- index.js</span><br><span class="line">|- dist</span><br><span class="line">    |- main.js</span><br><span class="line">    |- index.html</span><br></pre></td></tr></table></figure><p>webpack.config.js为webpack的配置文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">//webpack.config.js</span><br><span class="line">const path = require(&apos;path&apos;);//引入nodejs的path模块</span><br><span class="line">module.exports = &#123;</span><br><span class="line">  entry: &apos;./src/index.js&apos;,//设置入口js文件</span><br><span class="line">  output: &#123;</span><br><span class="line">    filename: &apos;bundle.js&apos;,//设置输出的js文件名</span><br><span class="line">    path: path.resolve(__dirname, &apos;dist&apos;//设置输出的地址</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">//path.resolve() 方法将路径或路径片段的序列解析为绝对路径</span><br><span class="line">//__dirname为项目根目录</span><br></pre></td></tr></table></figure><p>之后，我们再继续运行来打包看一下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build</span><br></pre></td></tr></table></figure><p>由于设置了输出文件的文件名，此时，文档结构改变为</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">    webpack_learn</span><br><span class="line">    |- node_modules</span><br><span class="line">    |- package.json</span><br><span class="line">    |- yarn.lock</span><br><span class="line">    |- webpack.config.js</span><br><span class="line">    |- src</span><br><span class="line">        |- let.js</span><br><span class="line">        |- get.js</span><br><span class="line">        |- index.js</span><br><span class="line">    |- dist</span><br><span class="line">+       |- bundle.js</span><br><span class="line">        |- main.js</span><br><span class="line">        |- index.html</span><br></pre></td></tr></table></figure><p>将index.html中的引入文件，改变为bundle.js,一样可以console出“大家好,我的名字是小明”</p><p><a href="https://www.webpackjs.com/configuration/" target="_blank" rel="noopener">配置项详细地址</a></p><p>一条一条刷配置的事情，我们先放到后面，一步一步来</p><p>讲到配置文件了，而且配置文件遵循<code>CommonJS规范</code>，那么，我们只需要遵守最终使用<code>module.exports</code>来输出配置对象即可，一开始也提到过了，每个使用模块的地方，只关心引入模块的结果，并不关心内部如何实现的，我们尝试将<code>webpack.config.js</code>文件修改为如下内容：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">//webpack.config.js</span><br><span class="line">const path = require(&apos;path&apos;);//引入nodejs的path模块</span><br><span class="line"></span><br><span class="line">module.exports = function(env,argv)&#123;</span><br><span class="line">    //配置函数接受两个参数env和argv</span><br><span class="line">    //env:环境对象</span><br><span class="line">    //Webpack-CLI 的命令行选项</span><br><span class="line">    console.log(env,argv,process.env.NODE_ENV,7);</span><br><span class="line">    return &#123;</span><br><span class="line">      entry: &apos;./src/index.js&apos;,//设置入口js文件</span><br><span class="line">      output: &#123;</span><br><span class="line">        filename: &apos;bundle.js&apos;,//设置输出的js文件名</span><br><span class="line">        path: path.resolve(__dirname, &apos;dist&apos;//设置输出的地址</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// path.resolve() 方法将路径或路径片段的序列解析为绝对路径</span><br><span class="line">// __dirname为项目根目录</span><br></pre></td></tr></table></figure><p>然后为加一个script</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    ...,</span><br><span class="line">    &quot;scripts&quot;: &#123;</span><br><span class="line">        ...,</span><br><span class="line">+       &quot;testParams&quot;: &quot;webpack --mode production --env.production product --param1 1 --param2 2 --explane 这是一个说明&quot;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后执行指令</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run testParams #也可以使用 yarn testParams</span><br></pre></td></tr></table></figure><p>查看终端的console记录</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&#123; production: &apos;product&apos; &#125; &#123;</span><br><span class="line">  _: [],</span><br><span class="line">  cache: null,</span><br><span class="line">  bail: null,</span><br><span class="line">  profile: null,</span><br><span class="line">  color: &#123; level: 3, hasBasic: true, has256: true, has16m: true &#125;,</span><br><span class="line">  colors: &#123; level: 3, hasBasic: true, has256: true, has16m: true &#125;,</span><br><span class="line">  mode: &apos;production&apos;,</span><br><span class="line">  env: &#123; production: &apos;product&apos; &#125;,</span><br><span class="line">  param1: 1,</span><br><span class="line">  param2: 2,</span><br><span class="line">  explane: &apos;这是一个说明&apos;,</span><br><span class="line">  &apos;info-verbosity&apos;: &apos;info&apos;,</span><br><span class="line">  infoVerbosity: &apos;info&apos;,</span><br><span class="line">  &apos;$0&apos;: &apos;node_modules\\webpack\\bin\\webpack.js&apos;</span><br><span class="line">&#125; 7</span><br></pre></td></tr></table></figure><p><code>env</code>参数为<code>{ production: &#39;product&#39; }</code></p><p><code>argv</code>参数包含了我们在package.json里写入的<code>param1</code>,<code>param2</code>,<code>explane</code>参数，我们可以根据script携带参数，来在webpack的配置文件里做一些操作</p><p>另外，这个文件也是支持promise来操作的<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">//webpack.config.js</span><br><span class="line">const path = require(&apos;path&apos;);//引入nodejs的path模块</span><br><span class="line"></span><br><span class="line">module.exports = function(env,argv)&#123;</span><br><span class="line">    //配置函数接受两个参数env和argv</span><br><span class="line">    //env:环境对象</span><br><span class="line">    //Webpack-CLI 的命令行选项</span><br><span class="line">    console.log(&apos;promise前&apos;,(new Date().getTime()));//promise前 1578884886284</span><br><span class="line">    return new Promse((resolve,reject)=&gt;&#123;</span><br><span class="line">        setTimeout(()=&gt;&#123;</span><br><span class="line">            console.log(&apos;promise后&apos;,(new Date().getTime()));//promise后 1578884889286</span><br><span class="line">            resolve(&#123;</span><br><span class="line">              entry: &apos;./src/index.js&apos;,//设置入口js文件</span><br><span class="line">              output: &#123;</span><br><span class="line">                filename: &apos;bundle.js&apos;,//设置输出的js文件名</span><br><span class="line">                path: path.resolve(__dirname, &apos;dist&apos;//设置输出的地址</span><br><span class="line">              &#125;</span><br><span class="line">            &#125;)</span><br><span class="line">        &#125;,3000)</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// path.resolve() 方法将路径或路径片段的序列解析为绝对路径</span><br><span class="line">// __dirname为项目根目录</span><br></pre></td></tr></table></figure></p><p>可以看出，使用Promise，可以使webpack三秒后打包</p><p>webpack也支持多次打包</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">module.exports = [</span><br><span class="line">    &#123;</span><br><span class="line">        mode: &apos;production&apos;</span><br><span class="line">        // 配置1</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        // 配置2</span><br><span class="line">    &#125;</span><br><span class="line">];</span><br></pre></td></tr></table></figure><p>关于使用配置文件，webpack是会默认寻找根目录下的<code>webpack.config.js</code>文件，所以执行指令的时候，执行的是</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npx webpack #这是简写模式</span><br><span class="line">npx webpack --config webpack.config.js #这是实际执行的模式</span><br></pre></td></tr></table></figure><p>webpack 可以通过–config指令，来指定使用哪个config文件来进行打包</p><p>例如</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">//package.json</span><br><span class="line">&#123;</span><br><span class="line">    &quot;scripts&quot;:&#123;</span><br><span class="line">        &quot;build1&quot;: &quot;webpack --config webpack.config.js&quot;,</span><br><span class="line">        &quot;build2&quot;: &quot;webpack --config webpack111111.config.js&quot;,</span><br><span class="line">        &quot;build3&quot;: &quot;webpack --config webpack222222.config.js&quot;,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>目前的内容，有一些什么问题呢？</p><p>我们在代码中，使用了<code>let</code>、<code>module.exports</code>等es6出的内容，众所周知，es6新加的内容，在一些老版本的浏览器里并不支持，就会报错，为了解决这种问题，我们就需要引入<code>babel</code>来将<code>es6</code>转化为<code>es5</code>，这样大部分老版本浏览器就支持了</p><p>这个时候，就要引入<code>webpack</code>的<code>loader</code>的概念，loader将在下一节记录</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;&lt;code&gt;webpack&lt;/code&gt;可以使用配置文件，也就是名为&lt;code&gt;webpack.config.js&lt;/code&gt;的文件，&lt;code&gt;webpack.config.js&lt;/code&gt;也是遵循&lt;code&gt;CommonJS规范&lt;/code&gt;的&lt;/p&gt;
&lt;figur
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="javascript" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
    
      <category term="javascript" scheme="http://www.meixiaohan.com/tags/javascript/"/>
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/tags/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/tags/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记5-loader</title>
    <link href="http://www.meixiaohan.com/2019/08/08/webpack_learn_5/"/>
    <id>http://www.meixiaohan.com/2019/08/08/webpack_learn_5/</id>
    <published>2019-08-07T16:00:00.000Z</published>
    <updated>2020-01-13T10:30:01.920Z</updated>
    
    <content type="html"><![CDATA[<h2 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h2><p><code>webpack</code> 的配置文件，也就是名为<code>webpack.config.js</code>的文件中，有一个<code>module</code>的属性配置，可以在此属性内，配置相关的规则</p><p>可以使用<code>module.rules</code>来进行规则匹配，键值为一个数组，分别传入不同的匹配规则<code>rule</code></p><blockquote><p>创建模块时，匹配请求的规则数组。这些规则能够修改模块的创建方式。这些规则能够对模块(module)应用 loader，或者修改解析器(parser)。</p></blockquote><p>每个<code>rule</code>可以分为三部分 - <code>条件(condition)</code>，<code>结果(result)</code>和嵌套规则<code>(nested rule)</code>。</p><p>例如：我们想给js文件，使用babel-loader来把es6代码转为es5代码</p><p>既然使<code>babel-loader</code>，那么我们首先需要安装<code>babel-loader</code>，根据<code>babel-loader</code>的<a href="https://www.npmjs.com/package/babel-loader" target="_blank" rel="noopener">npm社区</a>所写</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -D babel-loader @babel/core @babel/preset-env webpack</span><br></pre></td></tr></table></figure><p>建议使用<code>yarn</code>来安装</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add -D babel-loader @babel/core @babel/preset-env webpack</span><br></pre></td></tr></table></figure><p>然后将<code>webpack.config.js</code>中加入规则</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">    //webpack.config.js</span><br><span class="line">    const path = require(&apos;path&apos;);//引入nodejs的path模块</span><br><span class="line">    module.exports = &#123;</span><br><span class="line">      entry: &apos;./src/index.js&apos;,//设置默认</span><br><span class="line">      output: &#123;</span><br><span class="line">        filename: &apos;bundle.js&apos;,</span><br><span class="line">        path: path.resolve(__dirname, &apos;dist&apos;)</span><br><span class="line">      &#125;,</span><br><span class="line">+     module:&#123;</span><br><span class="line">+         rules:[&#123;</span><br><span class="line">+             //里面为匹配的规则</span><br><span class="line">+             test: /\.m?js$/,</span><br><span class="line">+             exclude: /(node_modules|bower_components)/,</span><br><span class="line">+             use: &#123;</span><br><span class="line">+                 loader: &apos;babel-loader&apos;,</span><br><span class="line">+                 options: &#123;</span><br><span class="line">+                     presets: [&apos;@babel/preset-env&apos;]</span><br><span class="line">+                 &#125;</span><br><span class="line">+             &#125;</span><br><span class="line">+         &#125;]</span><br><span class="line">+     &#125;</span><br><span class="line">    &#125;;</span><br></pre></td></tr></table></figure><p>然后再执行打包指令</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build #或者 yarn build</span><br></pre></td></tr></table></figure><p>然后打包后的代码，就没有了<code>let</code>与<code>module.exports</code>了，就可以在不支持<code>es6</code>的浏览器中使用了，如果要是用其他的<code>loader</code>，也可以使用哦</p><p><a href="https://www.webpackjs.com/loaders/" target="_blank" rel="noopener">webpack的loader列表</a></p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;h2 id=&quot;概念&quot;&gt;&lt;a href=&quot;#概念&quot; class=&quot;headerlink&quot; title=&quot;概念&quot;&gt;&lt;/a&gt;概念&lt;/h2&gt;&lt;p&gt;&lt;code&gt;webpack&lt;/code&gt; 的配置文件，也就是名为&lt;code&gt;webpack.config.js&lt;/code&gt;的文件中，有一个
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="javascript" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
    
      <category term="javascript" scheme="http://www.meixiaohan.com/tags/javascript/"/>
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/tags/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/tags/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
  </entry>
  
  <entry>
    <title>webpack学习笔记3-初次尝试打包</title>
    <link href="http://www.meixiaohan.com/2019/08/06/webpack_learn_3/"/>
    <id>http://www.meixiaohan.com/2019/08/06/webpack_learn_3/</id>
    <published>2019-08-05T16:00:00.000Z</published>
    <updated>2020-01-13T10:30:09.098Z</updated>
    
    <content type="html"><![CDATA[<p>这样就得到了一个安装上了webpack及其脚手架的项目</p><p>上一章创建的项目中，我们新建几个文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">    webpack_learn</span><br><span class="line">    |- node_modules</span><br><span class="line">    |- package.json</span><br><span class="line">    |- yarn.lock</span><br><span class="line">+   |- src</span><br><span class="line">+       |- let.js</span><br><span class="line">+       |- get.js</span><br><span class="line">+       |- index.js</span><br></pre></td></tr></table></figure><p>其中代码如下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">//let.js中↓↓↓↓↓↓</span><br><span class="line">let name = &apos;小明&apos;;</span><br><span class="line">module.exports = name;</span><br><span class="line"></span><br><span class="line">//get.js中↓↓↓↓↓↓</span><br><span class="line">module.exports = function(name)&#123;</span><br><span class="line">    console.log(name)</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">//index.js中</span><br><span class="line">let name = require(&apos;./let.js&apos;);</span><br><span class="line">let sayName = require(&apos;./get.js&apos;);</span><br><span class="line">sayName(&apos;大家好,我的名字是&apos;+name)</span><br></pre></td></tr></table></figure><p>然后，我们执行打包命令</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx webpack</span><br></pre></td></tr></table></figure><p>然后我们看到了，文档目录变成了</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">    webpack_learn</span><br><span class="line">    |- node_modules</span><br><span class="line">    |- package.json</span><br><span class="line">    |- yarn.lock</span><br><span class="line">    |- src</span><br><span class="line">        |- let.js</span><br><span class="line">        |- get.js</span><br><span class="line">        |- index.js</span><br><span class="line">+   |- dist</span><br><span class="line">+       |- main.js</span><br></pre></td></tr></table></figure><p>多出来了一个dist目录，和main.js文件，这个文件，就是被webpack所打包出来的文件，整合了let.js、get.js、index.js的所有js代码。</p><p>我们再修改一下目录</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">    webpack_learn</span><br><span class="line">    |- node_modules</span><br><span class="line">    |- package.json</span><br><span class="line">    |- yarn.lock</span><br><span class="line">    |- src</span><br><span class="line">        |- let.js</span><br><span class="line">        |- get.js</span><br><span class="line">        |- index.js</span><br><span class="line">    |- dist</span><br><span class="line">        |- main.js</span><br><span class="line">+       |- index.html</span><br></pre></td></tr></table></figure><p>新建一个index.html文件，并引入刚打包好的js文件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">//index.html</span><br><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">    &lt;head&gt;</span><br><span class="line">        &lt;meta charset=&quot;utf-8&quot;&gt;</span><br><span class="line">        &lt;title&gt;&lt;/title&gt;</span><br><span class="line">    &lt;/head&gt;</span><br><span class="line">    &lt;body&gt;</span><br><span class="line">        &lt;script src=&quot;./main.js&quot; type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;</span><br><span class="line">    &lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure></p><p>将这个文件运行到浏览器中，查看控制台，就可以看到打印了“大家好,我的名字是小明”。</p><p>这个地方使用了webpack的npx webpack打包指令</p><blockquote><p>可以这样说，执行 npx webpack，会将我们的脚本作为入口起点，然后 输出 为 main.js。Node 8.2+ 版本提供的 npx 命令，可以运行在初始安装的 webpack 包(package)的 webpack 二进制文件</p></blockquote><p>由表现，我们可以看出，配置项中</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">默认入口是/src/index.js</span><br><span class="line">默认出口为/dist/main.js</span><br></pre></td></tr></table></figure><p>我们也可以通过package.json来增加命令，来达到更好理解的编译指令，相当于给npm run 建了一个快捷方式</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">//package.json</span><br><span class="line">    &#123;</span><br><span class="line">      &quot;dependencies&quot;: &#123;</span><br><span class="line">        &quot;webpack&quot;: &quot;^4.41.5&quot;,</span><br><span class="line">        &quot;webpack-cli&quot;: &quot;^3.3.10&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;name&quot;: &quot;webpack_learn&quot;,</span><br><span class="line">      &quot;version&quot;: &quot;1.0.0&quot;,</span><br><span class="line">      &quot;main&quot;: &quot;index.js&quot;,</span><br><span class="line">      &quot;devDependencies&quot;: &#123;&#125;,</span><br><span class="line">      &quot;scripts&quot;: &#123;</span><br><span class="line">+       &quot;build&quot;:&quot;webpack&quot;,</span><br><span class="line">        &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;author&quot;: &quot;&quot;,</span><br><span class="line">      &quot;license&quot;: &quot;ISC&quot;,</span><br><span class="line">      &quot;description&quot;: &quot;&quot;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>这样，我们就可以使用快捷方式来打包啦</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build</span><br></pre></td></tr></table></figure><p>另外，对webpack传入指令 –mode可以指定开发模式 development为开发模式 production为生产模式，后面会提到</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">//package.json</span><br><span class="line">    &#123;</span><br><span class="line">      &quot;dependencies&quot;: &#123;</span><br><span class="line">        &quot;webpack&quot;: &quot;^4.41.5&quot;,</span><br><span class="line">        &quot;webpack-cli&quot;: &quot;^3.3.10&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;name&quot;: &quot;webpack_learn&quot;,</span><br><span class="line">      &quot;version&quot;: &quot;1.0.0&quot;,</span><br><span class="line">      &quot;main&quot;: &quot;index.js&quot;,</span><br><span class="line">      &quot;devDependencies&quot;: &#123;&#125;,</span><br><span class="line">      &quot;scripts&quot;: &#123;</span><br><span class="line">        &quot;build&quot;:&quot;webpack&quot;,</span><br><span class="line">+       &quot;dev&quot;:&quot;webpack --mode development&quot;,</span><br><span class="line">+       &quot;product&quot;:&quot;webpack --mode production&quot;,</span><br><span class="line">+        &quot;showColorAndProgress&quot;:&quot;webpack --progress --colors&quot;,</span><br><span class="line">        &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span><br><span class="line">      &#125;,</span><br><span class="line">      &quot;author&quot;: &quot;&quot;,</span><br><span class="line">      &quot;license&quot;: &quot;ISC&quot;,</span><br><span class="line">      &quot;description&quot;: &quot;&quot;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>这样，可以使用</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">npm run product#运行生产模式</span><br><span class="line">npm run dev#运行开发模式</span><br><span class="line">npm run showColorAndProgress#运行开输出带进度及颜色的编译</span><br></pre></td></tr></table></figure><p>备注：</p><ul><li>开发环境会包含devDependencies及dependencies中的依赖包</li><li>生产环境只会包含dependencies中的依赖包</li></ul><p>小技巧：</p><p>可以通过webpack-cli的一些参数，来让webpack的编译更有趣一些</p><ul><li>–progress  显示合并代码进度</li><li>-p 对打包后的文件进行压缩</li><li>-d 提供SourceMaps，方便调试，方便排查打包速度瓶颈。</li><li>–profile 输出性能数据，可以看到每一步的耗时</li><li>-display-modules 默认情况下 node_modules 下的模块会被隐藏，加上这个参数可以显示这些被隐藏的模块</li><li>–display-error-details 方便出错时能查阅更详尽的信息（比如 webpack 寻找模块的过程），从而更好定位到问题。</li><li>–config：指定一个 Webpack 配置文件的路径；</li><li>–mode：指定打包环境的 mode，取值为development和production，分别对应着开发环境和生产环境；</li><li>–json：输mode出 Webpack 打包的结果，可以使用webpack –json &gt; stats.json方式将打包结果输出到指定的文件；</li><li>–watch, -w：watch 模式打包，监控文件变化之后重新开始打包；</li><li>–color, –colors/–no-color, –no-colors：控制台输出的内容是否开启颜色；</li><li>–hot：开启 Hot Module Replacement模式，后面会详细介绍；</li></ul>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;这样就得到了一个安装上了webpack及其脚手架的项目&lt;/p&gt;
&lt;p&gt;上一章创建的项目中，我们新建几个文件&lt;/p&gt;
&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=
      
    
    </summary>
    
    
      <category term="webpack" scheme="http://www.meixiaohan.com/categories/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="javascript" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/categories/webpack/web%E5%89%8D%E7%AB%AF/javascript/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
    
      <category term="javascript" scheme="http://www.meixiaohan.com/tags/javascript/"/>
    
      <category term="webpack" scheme="http://www.meixiaohan.com/tags/webpack/"/>
    
      <category term="web前端" scheme="http://www.meixiaohan.com/tags/web%E5%89%8D%E7%AB%AF/"/>
    
      <category term="学习笔记" scheme="http://www.meixiaohan.com/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
      <category term="打包工具" scheme="http://www.meixiaohan.com/tags/%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7/"/>
    
  </entry>
  
</feed>
