【译】为前端开发准备的webpack4注解


使用前端开发的webpack4注解
现在,web开发变得愈发复杂,因此须要引入其余工具协助咱们开发网站。下面介绍一个现实开发中关于webpack4配置的完整例子。
开发一个现代化的网站已经成为流行的开发方式。也指望网站提供更多的功能,而不只仅是具备市场的宣传效果,由于它还具备传统APP的功能。
一旦系统功能变复杂了,就须要把功能分解成组件,使用工具自动编译打包。不管是造车,起草法律文件仍是建网站,都是如此。

工做使用合适的工具复制代码
像webpack这样的工具已经成为现代前端开发的首选,缘由如前面描述的:构建复杂的程序。
正如webpack4大加宣扬的几个特性,最吸引个人恐怕就是更加快速的构建。因此我决定使用它。
打起精神,由于这不只是篇文章,并且干活慢慢。

试用webpack
几年前,我发布过一篇文件《试用Gulp构建前端自动化》,文章详细介绍了试用Gulp达到这一效果。然而,在开发期间,我对Vuejs还有GraphQL作了大量的研究,在文章《Vuejs和GraphQL实战》有详细描述。
我发现webpack使用流行的工具链轻易地构建出各类类型的网站和应用。
其余的选择:
  • Laravel Mix,在webpack基础上抽象出的层,简洁易用:快速上手、构建快速,而且能支持客户近90%的需求。剩下的10%你不管如何都是要详细研究webpack了。不足的就是还不支持webpack4。
  • vue-cli,若是你是vue前端开发者,那么应该足够吸引你。这个也是在webpack基础上的抽象,多数场景下都能工做的很好。可是若是想分离它内置的功能也只能深刻研究webpack了。我不是一直使用Vuejs的。
  • Neutino,这是一个构建在webpack基础的颇有意思的一个抽象,在博文《Neutrino: How I Learned to Stop Worrying and Love Webpack》有详细的描述。设计理念很不错,经过将预置的组件平凑在一块儿来构建webpack配置。
你选择上面的任何一个(或者是其余的)我都不会指责你,可是请谨记,他们都有一个共同的特性:webpack的抽象层。

理解在开发系统中各层是如何工做的、效果如何复制代码
最终,你只须要决定你但愿在前端技术金字塔中的位置。有时候,咱们须要理解像webpack这样重要的工具是如何工做是颇有意义的。
刚才,我和Sean Larkin(webpack的核心团队成员)关于webpack像一个“黑盒子”有过争论,他的回答虽然简练可是却直中要害:
若是你不打开它也只是黑盒
他说的很对。如今咱们开始打开这个盒子。
这篇文章不是教你学习webpack或者是怎么安装。这已经有不少教程了:

还有不少。这篇文章意在介绍一个至关复杂的webpack4的完整配置。你也可能都用得上;也可能只用一点。仍是但愿你们能从中学习一二。
在学习webpack的过程当中,我发现了不少视频教程,不少知识简单的安装和一些基本配置,不是完整的从实际项目出发的webpack 配置项。因此咱们会和盘托出。

从webpack盒子里咱们能获得什么
当我开始打开这个盒子学习webpack时,我列举了它所依赖的技术列表,我想这能够成为构建的一部分。我也曾花时间环顾四周,看看有什么使用的工具。
像在《A Pretty Website Isn't Enough》讨论过的,网站性能是一个常常被关注的核心指标,因此咱们将注意力放到webpack的配置上也是很天然的事情。
从我本身对webpack的需求出发,列举了一下在构建过程当中使用的技术点:
  • Development/Production, 本地开发环境,我指望使用webpack-dev-server在内存中快速构建。发布构建(一般在Docker容器内完成),我又指望全部可能的优化。所以,须要把dev和prod配置分开。
  • Hot Module Replacement,一旦我更改了javascript,css 或者template文件,我但愿web页面能“悄悄”刷新。这种开发速度是惊人的:不须要刷新按钮。
  • Dynamic Code Splitting,我不想在配置文件中定义chunk,但愿webpack能替我梳理处理。
  • Lazy Loading,又叫异步动态模块加载。只加载须要的代码或资源,加载资源不阻塞render。
  • Modern& Legacy JS Bundles, 我但愿部署支持75%以上浏览器的ES2015 module,同时优雅地为旧版浏览器提供后备旧版bundle包(编译后的代码和垫片)
  • Cache Busting via manifest.json, 支持给静态资源设置超长的过时时间,即便资源发生改变也能自动缓存。
  • Critical CSS,详细的见《Implement Critical CSS on your website》,使初始页的加载速度显著提升。
  • Workbox Service Worker,咱们能够利用Google的Workbox项目生成一个ServiceWorker,以了解咱们的静态资源。PWA,咱们来了。
  • PostCSS,能够当作“Bable of CSS”,在这个基础上构建出SASS和SCSS,支持即将发布的CSS特性。
  • Image Optimization,在多数的web页面中图片占了最大的一部分,因此使用自动化的工具如mozjpeg,optipng,svgo仍是颇有意义的。
  • Automatic.webp Creation,Chrome,Edge和Firefox都已经支持.webp,这是一种比JPEG更加高效的格式。
  • Vuejs,vuejs是我前端框架的备选项,我但愿可以使用单个文件.vue组件做为我开发过程的无缝部分。
  • Tailwind CSS,Tailwind是一个实用为先的工具集,本地能快速开发。使用PurgeCSS编译上线包,并显著减小包的大小。
看,这是一个多么有雄心的列表。
还有更多,像自动JavaScript压缩,CSS压缩和前端构建系统须要咱们须要的标准工具。
我还但愿它与开发团队合做,开发团队能够为他们的本地开发环境使用不一样的工具,并使配置易于维护和项目之间的重用。

可维护性和可重用性的重要性不容低估

你的前端框架/技术堆栈可能与个人不一样,但应用的原则是相同的。 因此请继续阅读,不管你使用什么!

项目目录树和代码组织
咱们先看概览一下生成的目录骨架结构:


完整的项目代码,能够checkout出 annotated-webpack4-config github库。
就核心配置文件而言,咱们有以下配置:
  • .env,webpack-dev-server指定的环境配置项,该项不该提交到git库。
  • webpack.setting.js, 一个JSON风格配置文件,这是项目之间惟一须要修改的地方。
  • webpack.common.js,两个环境相同的配置项。
  • webpack.dev.js,本地开发环境配置脚本。
  • webpack.prod.js,上线环境打包配置脚本

如今用图片描述下这些都是怎么配合工做的;


目标就是在项目中应用,你只须要修改黄色圆角矩形部分(.env和webpack.settings.js)。
以这种方式分离出来,使得配置文件的使用变得更加容易。 即便您最终更改了我在此处提供的各类webpack配置文件,保持这种配置方法也有助于长期维护。
不要担忧,稍后咱们会详细介绍各个文件。

package.json注解
下面咱们经过分解package.json的方式开始这一过程:
这里没有什么特殊关注的,仅仅是些package.json规范约定的元信息项。
配置两个脚本,意味着为咱们的项目支持两个构建步骤。
  • dev,本地什么时候候运行,都会拉起webpack-dev-server,并之内存方式支持热模块替换(HMR)及其余的特性 。
  • build,该命令在生产部署时使用,它完成了生产部署须要完成的全部花哨和耗时的事情,如Crit­i­cal CSS,JavaScript的压缩等。
在开发环境中,若是你使用yarn,能够在Cli命令行执行 yarn dev或者yarn build。若是使用npm,能够执行npm run dev或npm run build。这仅是两条运行脚本的命令。
注意到使用 --config 参数,传递到多个配置文件中,这使咱们能够将webpack配置分解为单独的逻辑文件,由于与生产版本相比,咱们将为开发构建作不少不一样的事情。
下面咱们看browserslist:
这是一个基于人类可读配置的特定浏览器的表。 PostCSS autoprefixer默认使用咱们的生产设置。 咱们将legacyBrowsers和modernBrowsers传递给Babel来处理遗留和现代JavaScript包的构建。 稍后会详细介绍!
下面看devDe­pen­den­cies,这里指定了构建系统须要的全部的npm包:
这里有至关多的包,构建过程也确实复杂。
最后,咱们使用denpendencies指定在网站前端要使用的包:
很显然,一个真实的网站或APP,这个字段中会有不少的依赖包;可是咱们如今只关注构建过程。

webpack.setting.js注解
我曾经用过相同的方法在《A Better package.json for the Frontend artical》,这是为了锁定从项目到项目的配置变为单独的webpack.settings.js,并保持webpack配置自己不变。

关键理念是咱们须要在项目之间编辑的惟一文件是webpack.settings.js复制代码
由于大部分的项目都具备类似的配置,因此咱们能够为多数项目建立一套webpack配置。须要修改的无非就是怎么操做数据。
所以,咱们的webpack.settings.js文件(项目之间的数据变动)和咱们的webpack配置中的内容(如何操做数据以产生最终结果)之间的关注点分离。



咱们将在webpack配置部分介绍全部这些内容。 这里须要注意的重要一点是,咱们已经采起了从项目到项目的更改,并将它们从webpack配置中分离出来,并转换为单独的webpack.settings.js文件
这意味着咱们能够在webpack.settings.js文件中定义每一个项目的不一样之处,而没必要对webpack配置频繁改动。
即便webpack.settings.js文件只是JavaScript,也尽可能将其保留为JSON风格,因此咱们只是更改其中的简单设置。 我没有使用JSON文件格式,也容许添加注释。

连接常见的WEBPACK配置约定
我为全部webpack配置文件(webpack.common.js,webpack.dev.js和webpack.prod.js)采用了一些约定,以使配置更加一致。
每一个config文件有两个内部配置项:
  • legacyConfig,该配置项会应用到遗留的ES5构建。
  • modernConfig,该配置会应用到现代的ES2015+构建。
咱们这样作是由于有单独的配置来建立遗留和现代的构建。 这使它们在逻辑上分开,webpack.common.js也有一个baseConfig; 这纯粹是代码组织要求的。
能够把它想象成OOP,当多个配置继承时,baseConfig就是那个基类。
我为保持配置清晰和可读而采用的另外一个约定是为各类webpack插件和须要配置的其余webpack片断配置configure()函数,而不是所有内联。
我这样作是由于来自webpack.settings.js的一些数据须要在webpack使用以前进行转换,而且因为双重遗留/现代构建系统,咱们须要根据构建类型返回不一样的配置。
它还使配置文件更具可读性。
做为通常的webpack概念,要了解webpack自己只知道如何加载JavaScript和JSON。 要加载其余任何东西,须要使用加载器。 咱们将在webpack配置中使用许多不一样的加载器。

webpack.common.js注解
如今让咱们看一下webpack.common.js配置文件,它包含dev和prod构建类型共享的全部设置。
在前面,咱们引入了须要的Node包,以及咱们使用的webpack插件。 而后咱们将webpack.settings.js导入为settings,以便访问定义的设置,并将package.json做为pkg导入,以便访问那里的一些设置。


配置函数
configureBabelLoader()函数以下:
configureBabelLoader函数配置babel-loader处理加载的全部的js文件。使用@babel/preset-env代替.babelrc文件,因此咱们能够将全部内容保留在咱们的webpack配置中。
Babel能够编译现代ES2015+ JavaScript文件(还支持其余文件如:TypeScript或coffeeScript),编译成目标浏览器能够识别的代码。
咱们将browserList做为参数传入,这样咱们就能够为旧版浏览器构建现代ES2015 +模块和带polyfill的传统ES5 JavaScript。
在HTML文件中,仅仅添加以下:
没有垫片,没有小题大作。老款浏览器会忽略type="module",加载main-legacy.js。现代浏览器加载main.js,会忽略nomudule。这是很是明智的,在vue-cli3中已经采起了这种策略。
@babel/plugin-syntax-dynamic-import插件容许咱们在Web浏览器实现ECMAScript动态导入提议以前进行动态导入,这使咱们能够异步加载JavaScript模块,并根据须要动态加载。
这个是什么意思呢?意味着咱们能够像下面这么作:
主要作了两个主要事情:
一、经过/* webpackChunkName: "vue" */ 注释,已经告诉webpack咱们但愿这个动态代码拆分块被命名。
二、由于咱们在async main方法中使用import函数,await函数等待动态加载的JavaScript导入的结果,而其他的代码继续以其原来的方式执行。
咱们已经告诉webpack但愿代码块经过代码分割,而不是经过配置。 经过@ babel / plugin-syntax-dynamic-import的神奇功能,能够根据须要异步加载此JavaScript块。
请注意,咱们也使用.vue单个文件组件作了一样的事情。
除了使用await,咱们还能够在import后返回的Promise中执行咱们的代码:


在这里,咱们使用了Promise,而不是使用await,所以咱们知道动态导入已经生效,能够愉快地使用Vue了。
若是你关注过相似的问题,就能够看到咱们经过Promises有效地解决了JavaScript依赖关系。太好了!
咱们甚至能够在用户点击某些内容,滚动到某个位置或知足其余条件后加载某些JavaScript块等有趣的事情。 查看 模块方法import()了解更多信息。
若是有兴趣了解有关Babel的更多信息,请查看使用 Babel 7和Webpack文章
接下来咱们看下configureEntries():
在这里,咱们经过settings.entries从webpack.settings.js中提取webpack入口点。 对于单页应用程序(SPA),只有一个入口点。 对于更传统的网站,可能有几个入口点(每页模板可能有一个入口点)。
不管哪一种方式,由于咱们已经在webpack.settings.js中定义了咱们的入口点,因此很容易配置。 入口点实际上只是一个<script src =“app.js”> </ script>标签,咱们将在HTML中加入该标记以启动JavaScript。
既然咱们使用动态导入模块,因此在页面中仅有一个script标签;剩下的JavaScript按需加载。
下面看下configureFontLoader函数:
dev和prod构建的字体加载是相同的,因此咱们在这里定义。 对于咱们正在使用的任何本地字体,咱们能够告诉webpack在JavaScript中加载它们:
import comicsans from '../fonts/ComicSans.woff2';
下面是configureManifest函数:
这会为基于文件名的缓存清除配置webpack-manifest-plugin。 简而言之,webpack知道咱们须要的全部JavaScript,CSS和其余资源,所以它能够生成一个指向资源的内容哈希名称的清单


咱们传入一个文件名,由于咱们建立了一个现代的manifest.json和一个遗留的manifest-legacy.json,它们分别具备现代ES2015 +模块和传统ES5模块的入口点。 对于为现代和遗留构建而构建的资源,两个清单中的键都是相同的。
接下来看下标准的configureVueLoader:
这只是让咱们轻松加载 Vue单文件组件。 webpack负责为您提取适当的HTML,CSS和JavaScript。

基本配置
baseConfig与modernConfig和legacyConfig合并:
这里的全部内容都是很是标准的webpack配置,但请注意咱们将vue $别名为vue/dist/vue.esm.js,以便咱们能够得到Vue的ES2015模块版本。
咱们使用WebpackNotifierPlugin以友好的方式告诉咱们构建的状态。

遗留浏览器配置
legacyConfig用于使用适当的polyfill构建ES5遗留JavaScript:
请注意,咱们把pkg.browserslist.legacyBrowsers传递给configureBabel Loader(),而后将'manifest-legacy.json'传递给configureManifest()。
在此次编译中还使用到了CopyWebpackPlugin,因此咱们只须要在settings.copyWebpackConfig中定义一次拷贝文件。

现代浏览器配置
modernConfig用来构建现代ES2015 js模块。
请注意,咱们把pkg.browserslist.modernBrowsers传递给configureBabelLoader(),而后把mainfest.json传递到configureManifest方法

module.exports
最后,module.exports使用webpack-merge合并配置文件,返回一个对象,能够在webpack.dev.js和webpack.prod.js中使用。
注释webpack.dev.js
如今,让咱们看下webpack.dev.js,该配置文件包含了全部在开发阶段须要的build包,它与webpack.common.js中的设置合并,造成一个完整的webpack配置。
在前面,咱们再次引入了须要的Node包,以及使用的webpack插件。 而后咱们将webpack.settings.js导入为setting,以便咱们能够访问那里的设置,并将package.json做为pkg导入,以便访问那里的一些设置。
咱们还导入webpack.common.js经常使用webpack配置,将合并开发设置。

配置函数
下面是configureDevServer函数实现
进行生产构建时,webpack会捆绑全部各类资源并将它们保存到文件系统中。 相比之下,在本地开发时,经过webpack-dev-server使用开发构建:
  • 为咱们的静态资源提供服务的本地Express Web服务器
  • 为了提升速度,在内存而不是文件系统中构建咱们的静态资源
  • 将从新构建像JavaScript,CSS,Vue组件等资源,由于咱们更改它们并经过热模块替换(HMR)将它们注入网页而无需从新加载页面
  • 在更改模板时会从新加载页面

这相似于更复杂的Browsersync变体,并大大加快了开发速度。
惟一有点不经常使用的事情是使用 Sane监视未经过webpack运行的文件(在本例中为咱们的模板),以便在其中一个更改时执行整页从新加载。
请注意,webpack-dev-server的配置再次来自咱们的webpack.settings.js文件。 对于不少人来讲默认值可能没问题,可是使用 Laravel Homestead做为本地开发,正如 local development with Vagrant / Homestead文章中所讨论的那样。 这意味着要在Homestead VM中运行全部开发工具。
所以,不要在webpack.settings.js文件中对本地开发环境进行硬编码(由于它可能因团队中的人而异),webpack.settings.js能够从一个可选的.env文件中读取 拥有特定的devServer配置:
你有可能使用不一样的配置,所以根据须要在.env文件中根据须要更改设置。 .env背后的思想是在.env文件中放置了一个特定环境配置,咱们不会将它提交到git 库。 若是.env文件不存在,那很好,它只使用默认值:
咱们还使用PUBLIC_PATH .env变量(若是存在)来容许生成构建的每一个环境。 这样咱们就能够进行构建本地生产版本,或者在Docker容器中进行内容分发时构建,该容器使用可经过CDN分发URL构建。
下面看下configureImageLoader方法:
参数传入buildType,能够返回不一样的结果,具体取决于它是遗留构建仍是现代构建。 在这种状况下,返回相同的配置,但能够想象到这些可能会改变。
重要的是要注意,这仅适用于webpack构建中包含的图像; 许多其余图像未来自其余地方(CMS系统,资产管理系统等)。
要让webpack识别图像,应先将其导入:
import Icon from './icon.png';
检查webpack的文档 Loading Image部分,详细了解。

下面看下configurePostcssLoader部分:
咱们使用PostCSS来处理全部CSS,包括Tailwind CSS。 我认为它是CSS版的Babel,由于它将各类高级CSS功能编译成浏览器能够解析为普通CSS。
重要的是要注意,对于webpack加载器,它们按照定义的相反顺序进行处理:
请记住,由于这是咱们在本地开发中所作的事情,因此咱们不须要作任何花哨的事情就将全部CSS提取到最小化文件中。 相反,咱们只是让样式加载器在html文档中内联注入。
webpack-dev-server为css加载使用Hot Module Replacement(HMR),所以每当更改内容时,它都会从新编译CSS并自动从新注入。 这有点神奇。
以一下方式导入CSS:
import styles from '../css/app.pcss';
具体的在webpack的文档 Loading Image部分详细描述。
从App.js入口点开始; 将此视为PostCSS的切入点。 app.pcss文件@imports项目使用的全部CSS; 稍后将详细介绍。

module.exports
最后,module.exports使用webpack-merge包将webpack.common.js中的common.legacyConfig与开发遗留配置合并,并将common.modernConfig与开发现代配置合并:


module.exports返回一个数组,这就告诉webpack咱们须要完成多个编译:一个用于遗留构建,另外一个用于现代构建。
须要注意的是遗留构建,输出的JavaScript文件格式为[name]-legacy.[hash].js,现代构架的输出格式为[name].[hash].js。
经过将mode设置为“development”,咱们告诉webpack这是一个开发版本。
经过将devtool设置为'inline-source-map',咱们将CSS / JavaScript的.maps 内联到文件中。文件虽然变得庞大,但便于调试。
webpack.HotModuleReplacementPlugin支持的热模块替换(HMR)。
DashboardPlugin插件让咱们感受本身构建一个花哨的webpack的HUD:
我发现DashboardPlugin开发HUD比默认的webpack进度滚动更有用。
就是这样,咱们如今为项目提供了一个很好的开发构建; 查看热模块替换视频,了解此操做的示例:

注解WEBPACK.PROD.JS
如今让咱们看看webpack.prod.js配置文件,它包含了项目用于生产构建的全部设置。 它与webpack.common.js中的设置合并,造成一个完整的webpack配置。
再次引入了咱们须要的Node包,以及用到的webpack插件。 而后咱们将webpack.settings.js导入为setting,以即可以访问里面的设置,并将package.json做为pkg导入,以便访问一些设置。
咱们还导入咱们的webpack.common.js经常使用webpack配置,将合并成开发设置。

Tailwind 提取器
此类是Tailwind CSS的自定义PurgeCSS提取器,容许在类名中使用特殊字符。
这取自Tailwind CSS文档中删除未使用的CSS with PurgeCSS部分。 请参阅下文,了解此提取器如何与PurgeCSS配合使用,从而神奇地使CSS变得更加整洁。

配置函数
咱们看下configureBanner方法
这只是为咱们构建的每一个文件添加的含有项目名称,文件名,做者和git信息的banner。

如今看下configureBundleAnalyzer方法


使用WebpackBundleAnalyzer插件为咱们的现代和旧版bundle构建生成报告,生成一个自包含的交互式HTML页面,详细了解由webpack生成的bundle包中的确切内容。
【图片省略】
我发现帮助保持bundle包大小很是有用,而且确切地了解webpack正在构建什么,因此我已经将它做为生产构建过程的一部分。

如今看下configureCriticalCss方法:
这里使用CriticalCssPlugin经过咱们的webpack.settings.js中的settings.criticalCssConfig.pages进行分块,生成CriticalCSS。
请注意,若是传入的页面在其名称中的任何位置都有settings.criticalCssConfig.ampPrefix,则会经过传入很是大的高度为整个网页(而不只仅是上面的折叠内容)生成CriticalCSS。
我不会在这里详细介绍CriticalCSS; 有关CriticalCSS的更多信息,请查看您网站上的关键CSS文章。

下面看下configureCleanWebpack函数
使用CleanWebpackPlugin从webpack.settings.js中删除settings.paths.dist.base中的构建目录。

下面是configureHtml函数:
这将HtmlWebpackPlugin与WebappWebpackPlugin(见下文)结合使用,为咱们的favicons生成HTML。 请注意,咱们在templateContent中传入一个空字符串,以便输出只是WebappWebpackPlugin的原始输出。

下面看configureImageLoader


传入buildType参数,返回不一样的结果,具体取决于它是遗留构建仍是现代构建。 这种状况下,咱们可使用各类图像优化手段,而后经过img-loader进行构建。
咱们只对现代版本执行此操做,由于花费时间来优化现代版本和旧版本的图像是没有意义的(图像对于二者都是相同的)。
重要的是要注意,这仅适用于咱们的webpack构建中包含的图像; 许多其余图像未来自其余地方(CMS系统,资产管理系统等)。
以以下方式在JavaScript中导入图片:
import Icon from './icon.png';
能够检出webpack文档的Loading Image部分进行详细查看。

如今看configureOptimization方法:
这是咱们配置webpack生产版本优化的地方。 对于遗留构建(两次没有任何意义),咱们使用MiniCssExtractPlugin将项目范围内使用的全部CSS提取到单个文件中。 若是之前使用过webpack,那么过去是使用了ExtractTextPlugin来执行此操做。
而后,咱们还使用OptimizeCSSAssetsPlugin经过删除重复规则来优化生成的CSS,并经过cssnano压缩CSS。
最后,咱们将JavaScript最小化器设置为TerserPlugin; 这是由于UglifyJsPlugin再也不支持最小化ES2015 + JavaScript。 因为咱们正在生成ES2015 + bundle包,因此咱们须要它。

看下configurePostcssLoader方法:
这看起来很是相似于configurePostcssLoader()的dev版本,除了最后的加载器,使用MiniCssExtractPlugin.loader将全部的CSS提取到一个文件中。
只对遗留构建执行此操做,由于对每一个构建执行它没有任何意义(CSS是相同的)。 使用ignore-loader进行现代构建,所以咱们的.css和.pcss文件存在一个加载器,但它什么也没作。
如前所述,使用PostCSS处理全部CSS,包括Tailwind CSS。 我认为它是CSS的Babel,由于它将各类高级CSS功能编译成浏览器能够识别的普通CSS。
一样,重要的是要注意,对于webpack加载器,它们按照它们列出的相反顺序进行处理:

因为这是一个生产版本,咱们使用MiniCssExtractPlugin.loader提取全部使用的CSS,并将其保存到单个.css文件中。 CSS也被压缩的,针对生产进行了优化。
能够按以下方式导入pcss文件:
import styles from '../css/app.pcss';

这在webpack文档的Loading CSS部分中有详细讨论。
咱们以App.js入口点开始; 将此视为PostCSS的切入点。 app.pcss文件@imports咱们项目使用的全部CSS; 稍后将详细介绍。
下面看下configurePurgeCss函数:
Tailwind CSS是一个出色的实用优先的CSS框架,容许快速原型设计,由于在本地开发中,不多须要实际编写任何CSS。 相反,只需使用提供的实用程序CSS类。
缺点是生成的CSS可能有点大。 这就是PurgeCSS的用武之地。它将解析全部HTML /模板/ Vue /任何文件,并删除任何未使用的CSS。
节省的费用可能很大; Tailwind CSS和PurgeCSS是天做之合。 在Tailwind CSS实用程序 - Adam Wathan播客的第一个CSS上深刻探讨了这个问题。
它遍历settings.purgeCssConfig.paths中的全部路径globs,寻找要保留的CSS规则; 未找到的任何CSS规则都会从咱们生成的CSS构建中删除。
咱们还使用WhitelisterPlugin,当咱们知道咱们不但愿某些CSS被剥离时,能够轻松地将整个文件或全局列入白名单。 与咱们的settings.purgeCssConfig.whitelist匹配的全部文件中的CSS规则都列入白名单,而且永远不会从生成的构建中剥离。

如今看下configureTerser函数:
这只是配置TerserPlugin使用的一些设置,能够最小化咱们的遗留和现代JavaScript代码。
看下configureWebApp函数:
这使用WebappWebpackPlugin以无数种格式生成咱们全部的网站favicon,以及咱们的webapp manifest.json和其余PWA细节。
它与HtmlWebpackPlugin结合使用,还能够输出一个webapp.html文件,其中包含指向全部生成的favicons和相关文件的连接,以包含在咱们的HTML页面的<head> </ head>中。

下面看下configureWorkbox函数:
咱们使用Google的 WorkboxWebpackPlugin为咱们的网站生成服务。 这超出了本文的范围,但您能够查看 Going Offline:Service Workers with Jeremy Keith播客的入门文章。
配置所有来自webpack.settings.js中的settings.workboxConfig对象。 除了预先缓存现代构建manifest.json中的全部静态资源外,还可使用一个workbox-catch-handler.js来配置它以使用 fallback response catch-all route



Module.exports
最后,module.exports使用webpack-merge将webpack.common.js中的common.legacyConfig与生产遗留配置合并,并将common.modernConfig与生产现代配置合并:


经过在module.exports中返回一个数组,告诉webpack须要完成多个编译:一个用于咱们的遗留构建,另外一个用于咱们的现代构建。
请注意,对于遗留构建,将处理后的JavaScript输出为[name]-legacy.[hash] .js,而现代构建将其输出为[name].[hash].js。
经过将mode设置为'production',告诉webpack这是一个生产版本。 这样能够实现适合生产构建的许多设置。
经过将devtool设置为'source-map',咱们要求将CSS / JavaScript的.maps生成为单独的.map文件。 更容易调试实时生产,而无需添加静态资源的文件大小。
这里使用了几个咱们还没有涉及的webpack插件:
  • CreateSymlinkPlugin,这是我建立的一个插件,容许建立符号连接做为构建过程的一部分。 使用它将生成的favicon.ico符号连接到/favicon.ico,由于许多Web浏览器会在Web根目录中查找。
  • SaveRemoteFilePlugin,这是我建立的插件,用于下载远程文件并将其做为webpack构建过程的一部分。 我用它来下载并在本地保存Google的analytics.js。
  • ImageminWebpWebpackPlugin, 此插件会为项目导入的全部JPEG和PNG文件为.webp
就是这样,咱们如今为项目提供了一个很好的生产构建,包括全部的花里胡哨。

Tailwind css 和PostCSs配置
为了使webpack正确构建Tailwind CSS和其余CSS,还须要作一些设置。 感谢个人伙伴Jonathan Melville在构建这方面的工做。 首先咱们须要一个postcss.config.js文件:
这能够存储在项目根目录中; PostCSS将在构建过程当中自动查找它,并应用指定的PostCSS插件。 请注意,这是咱们包含tailwind.config.js文件的位置,以使其成为构建过程的一部分。
最后,CSS入口点app.pcss看起来像这样:
显然,包含了自定义CSS的任意组件/页面。

生成的项目代码树


在html页面注入script和css标签

总结
嗯,这是一个颇有潜力的工具! 当我第一次开始学习webpack时,就我很快意识到它是一个很是强大的工具,具备很是强大的功能。 你走多远取决于你想要潜水多远。
有关此处所示内容的完整源代码,请查看 annotated-webpack-4-config github库。
但愿这对你有所帮助,享受你的旅程,并作一些使人惊叹的东西!
相关文章
相关标签/搜索