<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          記一次給create-react-app提的PR

          共 6463字,需瀏覽 13分鐘

           ·

          2020-12-10 16:45

          關(guān)注公眾號(hào)?前端人,回復(fù)“加群

          添加無(wú)廣告優(yōu)質(zhì)學(xué)習(xí)群

          前言

          前些日子, 在項(xiàng)目發(fā)布的過程中CI突然報(bào)錯(cuò)了。我一看日志, 原來(lái)是來(lái)自于一段css代碼的報(bào)錯(cuò), 內(nèi)容大致如下:

          :root?{
          ??--swiper-navigation-size:?44px;
          }

          .swiper-button-next,.swiper-button-prev?{
          ??margin-top:?calc(var(--swiper-navigation-size)*-1/2)
          }
          1. 這段代碼為什么在run 的時(shí)候不報(bào)錯(cuò), 卻在 build的時(shí)候報(bào)錯(cuò)了呢?
          2. 那為什么又與 create-react-app 有關(guān)呢?
          3. 如何解決?

          本文就以上三個(gè)問題, 與大家展開討論。

          使用create-react-app創(chuàng)建項(xiàng)目

          create-react-app?css

          在App.css添加異常代碼

          :root?{
          ??--distance:?44px?+?44px;
          }

          .App?{
          ??margin-top:?calc(var(--distance)/2?*?-1);
          ??text-align:?center;
          }

          彈出項(xiàng)目webpack配置

          npm?run?eject

          打包項(xiàng)目

          npm?run?build

          定位到報(bào)錯(cuò)的loader

          既然錯(cuò)誤是與css有關(guān)的, 那么我們自然是找到webpack中關(guān)于css處理的部分。根據(jù)排除法, 我最后把目光鎖在了以下代碼:

          ???{
          ?????loader:?require.resolve('postcss-loader'),
          ?????options:?{
          ???????ident:?'postcss',
          ???????plugins:?()?=>?[
          ?????????require('postcss-flexbugs-fixes'),
          ?????????require('postcss-preset-env')({
          ???????????autoprefixer:?{
          ?????????????flexbox:?'no-2009',
          ???????????},
          ???????????stage:?3,
          ?????????}),
          ?????????postcssNormalize(),
          ???????],
          ???????sourceMap:?isEnvProduction???shouldUseSourceMap?:?isEnvDevelopment,
          ?????},
          ???}

          經(jīng)過調(diào)試我發(fā)現(xiàn)只需要將 postcss-preset-env中的stage設(shè)為大于3即可。

          那么 postcss-preset-env 各個(gè)配置分別代表什么意思呢?

          注意: 在沒有任何配置的情況下,postcss-preset-env會(huì)開啟stage 2階段的特性并支持所有瀏覽器

          stage:

          此屬性決定了哪些CSS特性需要被填充。

          stage共分為5個(gè)階段,分別是:

          • stage-0 非官方草案
          • stage-1 編輯草案或早期工作草案
          • stage-2 工作草案
          • stage-3 候選版本
          • stage-4 推薦標(biāo)準(zhǔn)

          features

          此屬性決定了哪些特性應(yīng)該被開啟或者關(guān)閉。

          browsers

          postcss-preset-env使用browserslist來(lái)配置目標(biāo)環(huán)境。

          autoprefixer

          postcss-preset-env集成了autoprefixer。那么問題就來(lái)到了 postcss-preset-env 與 stage 之間的關(guān)系了。

          探尋postcss-preset-envstage的奧秘

          根據(jù)官網(wǎng)對(duì)postcss-preset-env介紹:

          PostCSS Preset Env lets you convert modern CSS into something most browsers can understand, determining the polyfills you need based on your ?targeted browsers or runtime environments.

          簡(jiǎn)單地來(lái)說, PostCSS Preset Env 可以將現(xiàn)代的高級(jí)CSS語(yǔ)法轉(zhuǎn)換為大多數(shù)瀏覽器都能理解的內(nèi)容,根據(jù)目標(biāo)瀏覽器或運(yùn)行時(shí)環(huán)境確定所需的polyfill。

          我們直接進(jìn)入主題, 看 PostCSS Preset Env 這個(gè)包返回的是什么東西?

          import?cssdb?from?'cssdb';

          export?default?postcss.plugin('postcss-preset-env',?opts?=>?{
          ?
          ??const?polyfillableFeatures?=?cssdb.concat(
          ????//?additional?features?to?be?inserted?before?cssdb?features
          ????getTransformedInsertions(insertBefore,?'insertBefore'),
          ????//?additional?features?to?be?inserted?after?cssdb?features
          ????getTransformedInsertions(insertAfter,?'insertAfter')
          ??).filter(
          ????//?inserted?features?or?features?with?an?available?postcss?plugin
          ????feature?=>?feature.insertBefore?||?feature.id?in?plugins
          ??).sort(
          ????//?features?sorted?by?execution?order?and?then?insertion?order
          ????(a,?b)?=>?idsByExecutionOrder.indexOf(a.id)?-?idsByExecutionOrder.indexOf(b.id)?||?(a.insertBefore???-1?:?b.insertBefore???1?:?0)?||?(a.insertAfter???1?:?b.insertAfter???-1?:?0)
          ??).map(
          ????//?polyfillable?features?as?an?object
          ????feature?=>?{
          ??????//?target?browsers?for?the?polyfill
          ??????const?unsupportedBrowsers?=?getUnsupportedBrowsersByFeature(feature.caniuse);

          ??????return?feature.insertBefore?||?feature.insertAfter???{
          ????????browsers:?unsupportedBrowsers,
          ????????plugin:???feature.plugin,
          ????????id:???????`${feature.insertBefore???'before'?:?'after'}-${feature.id}`,
          ????????stage:????6
          ??????}?:?{
          ????????browsers:?unsupportedBrowsers,
          ????????plugin:???plugins[feature.id],
          ????????id:???????feature.id,
          ????????stage:????feature.stage
          ??????};
          ????}
          ??);

          ??//?staged?features?(those?at?or?above?the?selected?stage)
          ??const?stagedFeatures?=?polyfillableFeatures

          ??//?browsers?supported?by?the?configuration
          ??const?supportedBrowsers?=?browserslist(browsers,?{?ignoreUnknownVersions:?true?});

          ??//?features?supported?by?the?stage?and?browsers
          ??const?supportedFeatures?=?stagedFeatures;

          ??return?(root,?result)?=>?{
          ????const?polyfills?=?supportedFeatures
          ????return?polyfills;
          ??};
          });

          查看以上代碼我們發(fā)現(xiàn)它最后返回的是一個(gè)polyfills 數(shù)組。而歸根到底這個(gè)數(shù)組的內(nèi)容來(lái)自于 cssdb 這個(gè)包。

          那么這又是什么東西呢?

          根據(jù)官方解釋:

          cssdb?is?a?comprehensive?list?of?CSS?features?and?their?positions?in?the?process?of?becoming?implemented?web?standards.

          翻譯后大致的意思是: cssdb 是CSS功能及其在成為已實(shí)現(xiàn)的Web標(biāo)準(zhǔn)過程中的位置的完整列表。

          如果加上下面的源代碼示例, 大家可能會(huì)對(duì)這句話更容易理解一點(diǎn)。

          [
          ??...,
          {
          ??"id":?"custom-properties",
          ??"title":?"Custom?Properties",
          ??"description":?"A?syntax?for?defining?custom?values?accepted?by?all?CSS?properties",
          ??"specification":?"https://www.w3.org/TR/css-variables-1/",
          ??"stage":?3,
          ??"caniuse":?"css-variables",
          ??"docs":?{
          ????"mdn":?"https://developer.mozilla.org/en-US/docs/Web/CSS/var"
          ??},
          ??"example":?"img?{\n??--some-length:?32px;\n\n??height:?var(--some-length);\n??width:?var(--some-length);\n}",
          ??"polyfills":?[
          ????{
          ??????"type":?"PostCSS?Plugin",
          ??????"link":?"https://github.com/postcss/postcss-custom-properties"
          ????}
          ??]
          },
          ...
          ]

          至此,我們可以發(fā)現(xiàn)一個(gè)有趣的事情:

          1. postcss-preset-env 中的polyfills基本上都來(lái)自于 cssdb。

          2. 我們可以通過軟鏈(yarn link)的方式, 將這些包(postcss-preset-env)link到我們創(chuàng)建的項(xiàng)目。

          3. 然后直接將 postcss-preset-env 中node_modules下的 cssdb 的json文件中的 custom-properties 給移除掉。最后重新打包項(xiàng)目, 我們發(fā)現(xiàn)build通過了。

          4. 那么如果我們將它的stage修改為 2呢 ? 我們?cè)俅未虬l(fā)現(xiàn)打包依然通過了。

          5. 那么stage與 ?postcss-preset-env關(guān)系就很明顯了, 我們可以用下面這張圖表示:

          接下來(lái), 我們需要將目光聚焦于 postcss-custom-properties.

          深入挖掘postcss-custom-properties

          PostCSS Custom Properties lets you use Custom Properties in CSS, following the CSS Custom Properties specification.

          簡(jiǎn)言之, 它的作用就是讓你能夠在css中使用自定義的變量。除此之外還有很重要的一點(diǎn)就是:

          Note: This plugin only processes variables that are defined in the :root selector.(這個(gè)插件只處理 :root 下面的自定義變量)

          當(dāng)我們嘗試在官網(wǎng)的github中尋找答案時(shí), 可以從issue上入手。

          很快, 一個(gè)名為ParserError with plus or minus sign的issue引起了我的注意。

          我大致翻譯一下這個(gè)issue的內(nèi)容:

          在2018年12月28號(hào), andreymal 提了一個(gè)關(guān)于編譯失敗的issue.

          它試圖通過使用postcss來(lái)編譯

          :root?{
          ??--foowith:?50px?+?50px
          }?

          結(jié)果遇到了ParserError的錯(cuò)誤。

          在2019年4月份的時(shí)候, remithomas 它也遇到了ParserError的錯(cuò)誤。碰巧的是, 它編譯的代碼與我們的示例代碼似乎差不多

          ?calc(var(--gutter-width)*0.5*-1)

          與此同時(shí), 倉(cāng)庫(kù)的維護(hù)者 jonathantneal ?表明:

          切換到PostCSS Values Parser 3將是一項(xiàng)重大突破,他可以自己做到這一點(diǎn)。有人有興趣參加PR嗎?

          很快 remithomas

          當(dāng)即就回復(fù)了:

          I will do a PR to upgrade to PostCSS Values Parser 3。

          最后他提了一個(gè)pr 來(lái)解決這個(gè)issue下的問題.

          那么最后我們可以通過查看這個(gè)pr下的文件改動(dòng), 可以看到, 它升級(jí)了 postcss-values-parser(一個(gè)基于PostCSS的CSS屬性值解析器) 那么至此, 我們的問題已經(jīng)搞清楚了, 接下來(lái)我們需要關(guān)心的是, 如何解決這個(gè)問題。

          解決問題

          其實(shí)很簡(jiǎn)單, 我們只需要將對(duì)應(yīng)的依賴庫(kù)升級(jí)即可。

          因此我們?cè)囍鴮⒈镜豯ink的postcss-preset-env項(xiàng)目中postcss-custom-properties 升級(jí)至9.1.1即可。

          ok!我們重新打包 postcss-preset-env, 最后重新打包我們的項(xiàng)目。

          oh, 我們成功啦 ~

          提PR

          首先我們需要給 ?postcss-preset-env ?提一個(gè)PR, 請(qǐng)求升級(jí) postcss-custom-properties ?至9.1.1。不過似乎已經(jīng)有人提了, 這個(gè)PR目前還在進(jìn)行中。

          那么我們只能等到 postcss-preset-env 倉(cāng)庫(kù)的管理員合了這個(gè)PR, 才能給 create-react-app 提PR了。

          經(jīng)過這么一番探索, 我們發(fā)現(xiàn), 一開始提的 PR 并不合理, 因此我們需要關(guān)閉它, 并且需要在之前關(guān)聯(lián)的issue中表明我們的探索過程。

          寫在最后

          如果大家在項(xiàng)目中遇到類似的錯(cuò)誤, 可以將 postcss-preset-env fork到本地, 手動(dòng)去升級(jí) postcss-custom-properties 的版本, 最后關(guān)聯(lián)到項(xiàng)目中。

          完結(jié)!撒花 ~

          如果覺得本文有幫助, 請(qǐng)點(diǎn)個(gè)小小的贊哦, 謝謝啦~


          原文juejin.cn/post/6900700792391467021


          1.如果看到這里,說明你喜歡這篇文章,請(qǐng)?轉(zhuǎn)發(fā)、點(diǎn)贊在看

          2.關(guān)注公眾號(hào)前端人,回復(fù)資料包領(lǐng)取我整理的前端進(jìn)階資料包

          3.回復(fù)加群,加入前端進(jìn)階群,和小伙伴一起學(xué)習(xí)討論!

          瀏覽 70
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人黄片AV256 | 日韩aⅴ网站 | 国产调教视频 | 波多野结衣亚洲一区 | 国产自产21区 |