不幸的是,我现在没有时间/热情来维护这个项目。我建议分叉这个项目,或者阅读它的源代码以了解它是如何构建的。
此 webpack 样板适用于希望快速创建静态网站的初学者、中级和高级开发人员,同时实现所有正确的优化,以在 Google Page Speed Insights 和 Google Lighthouse Reports 上获得完美成绩- 这是 tris-gulp-boilerplate 的演变,现在带有Webpack 4。Webpack 是捆绑 JS 的新标准,而 Gulp 无法做到这一点。值得庆幸的是,Webpack 既可以运行任务,也可以捆绑 js?
该项目/样板的目标是覆盖以下人群:
初学者? ——尽管使用 Gulp/Webpack/Node/Npm 仍然需要比更熟悉的开发人员更彻底的解释。他们希望事情能够顺利进行,但他们也想知道如何以及为什么。
业余项目骗子?♀️——那些拥有所有伟大想法但不想浪费时间进行设置的人。他们需要将自己的想法、应用程序和网站快速地传送到浏览器中。
强迫症♂️——那些喜欢在性能和优化报告上获得完美分数的人。以数字方式组织的人们并自豪地知道他们的所有文件都已最小化、压缩、压缩并准备好发送!
请随意分叉此存储库并基于此模板创建您自己的工作流程!每个人都有点不同,我理解。
运行之前,您的计算机上需要有 git 和 node.js。
git clone https://github.com/tr1s/tris-webpack-boilerplate.git your-project-name
cd your-project-name && rm -rf .git
npm install
npm start
一切就绪,开始编码吧??!
如果您想 100% 全新开始和/或创建您自己的 Sass 工作流程,请删除src/styles/
文件夹、 src/index.html
和src/index.scss/
中的所有内容。我的文件夹结构基于 7-1 模式。
当您准备好将网站上传到您选择的 FTP/托管平台时,请npm run build
。这将创建一个dist
文件夹,其中包含优化和压缩的所有网站资源。
如果您想深入了解一切如何运作,请阅读以下功能。否则,继续编码并享受乐趣:)
tris-webpack-样板
用法
特点/内容
特性解释
Webpack 配置拆分
Webpack 开发服务器
HTML 资源和缩小
404页面未找到
SCSS 到 CSS + 优化
ES6 转译
浏览器列表
图片资源+压缩
字体加载+预加载
资产压缩
干净的 Webpack 插件
源图
网站图标生成
先离线再缓存
渐进式网络应用程序 (PWA)
陷阱的
贡献
我们不会使用一个大的webpack.config.js
,而是将生产和开发版本拆分为两个新的配置,分别称为webpack.dev.js
和webpack.prod.js
。我们想要的开发和生产配置将位于webpack.common.js
配置中。
当我们运行npm start
时,它将基于webpack.dev.js
配置运行开发构建,该配置还具有合并的webpack.common.js
配置。在 Webpack 文档中阅读更多相关内容。
/* wenpack.dev.js */const merge = require("webpack-merge");const common = require("./webpack.common.js");/* 合并 webpack.common.js 然后添加你的额外 */module.exports = merge(common, { 模式:“开发”, /* 其余代码放在这里 */});
当我们运行npm run build
时,它将基于webpack.prod.js
配置运行生产构建,该配置还具有合并的webpack.common.js
配置。
/* webpack.prod.js */const merge = require("webpack-merge");const common = require("./webpack.common.js");/* 合并 webpack.common.js 然后添加你的额外 */module.exports = merge(common, { 模式:“生产”,});
我们希望我们的开发和生产版本能够在浏览器中直观地产生相同的结果。您不想完成编码,运行构建,然后构建一个完全不同的网站,例如缺少图像。这就是为什么我们有webpack.common.js
来处理所有加载器和资产管理。 webpack.dev.js
与轻量级源映射略有不同。最后, webpack.prod.js
将处理将网站投入生产的所有最后阶段。即图像压缩、资产压缩 (gzip)、资产缩小、图标生成、缓存以及创建离线优先体验。
我将在下面详细介绍每个过程。
webpack-dev-server 在 package.json 中配置。 npm start
将运行服务器并使用webpack.dev.js
配置在浏览器中打开您的项目。 npm start
是npm的默认脚本,因此不需要向其添加run
。但对于构建脚本,您需要输入npm run build
。
"scripts": { "start": "webpack-dev-server --open --config webpack.dev.js", "build": "webpack --config webpack.prod.js"},
我们使用 html-loader 将 HTML 导出为字符串并缩小输出。这允许您在src/index.js
中导入src/index.html
。我们可以简单地使用加载器选项minimize: true
HTML,这就是为什么我们将其保留在webpack.common.js
而不是将其移动到webpack.prod.js
中。
/* webpack.common.js */{ 测试:/.html$/, 使用:[{loader:'html-loader',选项:{最小化:true} }]},
/* src/index.js */import "./index.html";
然后,我们使用 html-webpack-plugin 创建一个新生成的index.html
其中包含所有正确的资源导入。
template:
选项是您从中提取源 HTML 的位置。您可以使用自己的 html 模板、车把模板或任何其他模板。
inject:
选项是您的资产将去往的地方。默认情况下,Webpack 会将捆绑的webpack-bundle.js
脚本放在 body 的底部,但这里我将其切换到head
因为我们将使用 script-ext-html-webpack-plugin defer
脚本并将其放置在网站的头部。这有助于提高性能。
/* webpack.common.js */const HtmlWebpackPlugin = require('html-webpack-plugin');const ScriptExtHtmlWebpackPlugin = require("script-ext-html-webpack-plugin");插件: [ new HtmlWebpackPlugin({标题: 'tris-webpack-boilerplate',文件名: 'index.html',模板: './src/index.html',注入: 'head' }), new HtmlWebpackPlugin({标题: 'tris-404-page',文件名: '404.html',模板: './src/404.html',注入: 'head' }), 新的 ScriptExtHtmlWebpackPlugin({defaultAttribute: 'defer' }),],
如果您要拥有一个多页面网站,请继续添加更多new HtmlWebpackPlugin({})
插件。使用title:
key。
Netlify 是一项出色的免费服务,可让您管理和部署您的网站。 Netlify 会自动搜索404.html
,并在有人尝试打开您网站上的损坏链接时加载该页面。所以您无需担心。
如果您使用其他服务,请研究一下如何链接您的404.html
页面以使其处于活动状态。如果人们访问了损坏的链接,这是将他们送回到您的主页的好方法。
为了使用 Sass/SCSS,我们需要使用一些加载器来获得我们想要的结果。 css-loader、postcss-loader 和 sass-loader。
test:
正在使用 regex(正则表达式)检查是否有任何 sass、scss 或 css 文件,然后通过这三个加载器运行它们,该加载器包装在 mini-css-extract-plugin 周围,然后为您生成一个 CSS 文件在生产中使用。
阅读有关加载器概念的更多信息。
/* webpack.common.js */{ 测试:/.(sa|sc|c)ss$/, use: [MiniCssExtractPlugin.loader,{ loader: 'css-loader', options: {sourceMap: true }},{ loader: 'postcss-loader', options: {sourceMap: true }},{ loader: 'sass-loader ', 选项: {sourceMap: true }} ]},
加载程序序列的第二部分是postcss-loader
,您将在其中缩小和自动添加 CSS 前缀。为此,我们在项目的根目录创建一个postcss.config.js
并像这样配置它......
/* postcss.config.js */const purgecss = require("@full human/postcss-purgecss");module.exports = { 插件:[require(“autoprefixer”),require(“cssnano”)({预设:“default”,}),purgecss({内容:[“./**/*.html”],关键帧:true,} ), ],};
如果需要的话,请阅读 autoprefixer 和 cssnano 以根据您的喜好进行配置。另外,请总体阅读 postcss,因为它是您的武器库中非常强大的工具。
Purgecss 是一个很棒的 postcss 插件,用于删除代码中未使用的 css。 Purgecss 分析您的内容和 css 文件。然后,它将文件中使用的选择器与内容文件中的选择器进行匹配。它会从 css 中删除未使用的选择器,从而生成更小的 css 文件。
默认情况下它已准备就绪,但如果您想亲自对其进行直观测试,请取消注释@import "../node_modules/bulma/bulma";
在index.scss
中,然后运行npm run build
并查看 dist 文件夹中生成的webpack-bundle.css
。您会注意到没有那么多代码。然后从postcss.config.js
中删除 purgecss 并再次运行npm run build
,您会注意到 css 中有 10,000 多行代码来自 Bulma 框架。正如您所看到的,purgecss 非常适合删除您在使用 Bootstrap、Foundation、Bulma 等大型框架时不使用的 CSS!
mini-css-extract-plugin 是最后一步,因为它提取 CSS 并在输出之前为其命名。
/* webpack.common.js */const MiniCssExtractPlugin = require("mini-css-extract-plugin");plugins: [ new MiniCssExtractPlugin({filename: 'webpack-bundle.css',chunkFilename: '[id].css' })],
所以基本上... css-loader
将从应用程序中引用的所有 css 文件中收集 CSS 并将它们放入一个字符串中。然后postcss-loader
自动前缀并缩小你的样式,然后sass-loader
将其转换为 JS 模块,然后mini-css-extract-plugin
将 JS 模块中的 CSS 提取到单个 CSS 文件中以供 Web 浏览器解析。
您可能想使用最新的 JavaScript 功能和语法,但并非所有浏览器都支持它们。 Babel 会为我们处理这个问题。
在这里,我们测试所有 js 文件,但不包括node_modules
文件夹,然后通过带有 babel-preset-env 预设的 babel-loader 运行它。
/* webpack.common.js */{ 测试:/.js$/, 排除:/(node_modules)/, 使用:{loader:'babel-loader',选项:{预设:['@babel/preset-env']} }}
这次我们将冒险进入webpack.prod.js
文件。当我们npm run build
时,我们的输出 js 将被缩小并具有完整的源映射。通过npm start
在开发模式下运行,我们仍然会有更轻的源映射,但 js 不会被缩小。
/* webpack.prod.js */const TerserPlugin = require("terser-webpack-plugin");module.exports = merge(common, { 模式:“生产”, devtool:“源映射”, 优化:{minimizer: [ new TerserPlugin({test: /.js(?.*)?$/i,parallel: true,sourceMap: true, }),], },});
阅读简洁文档中有关选项的更多信息。
在这里,我们希望有一个地方可以告诉某些工具我们想要添加对哪些浏览器的支持。我们使用 browserslist 以及项目根目录中相应的.browserslistrc
文件来实现此目的。 Autoprefixer 和 babel-present-env 将获取此文件并根据配置应用它所需的内容。
了解您还可以传递到.browserslistrc
中的内容,并使用 browserl.ist 来查看您的配置将专门针对哪些浏览器。好吧,我想我已经说过浏览器足够多次了?
/* .browserslistrc */> 0.25%没有死
首先,我们使用 regex(正则表达式)测试 jpeg、jpg、png、gif 和 svg,然后使用 file-loader,它将文件的导入和需求解析为 url,然后将文件发送到输出目录。因此,如果您使用<img>
元素从src/images
文件夹中获取文件,它将被导入并发送到指定的输出路径images
。如果你npm start
(运行开发)或npm run build
(运行构建),最终会成为src/images
。
/* webpack.common.js */{ 测试:/.(jpe?g|png|gif|svg)$/, use: [{loader: '文件加载器',options: { name: '[name].[ext]', outputPath: 'images/', publicPath: 'images/'}, }]},
现在我们只想在npm run build
上优化我们的图像,因此我们如下编辑webpack.prod.js
。
我们再次使用正则表达式测试 jpeg、jpg、png、gif 和 svg,并应用适当的优化。 gifsicle
是一个无损 gif 压缩器, pngquant
是一个有损 png 压缩器,我们可以添加一个名为imageminMozjpeg
的额外插件来执行有损 jpg/jpeg 压缩。一个安全的选择是将质量设置在 75-90 之间,您应该获得一些不错的压缩,而不会损失可见质量。
我建议坚持使用无损压缩,并在添加到项目之前将图像裁剪到正确的尺寸。只需删除 imageminMozjpeg 和 pngquant 关键部分即可。
您还可以使用tinypng进行图像压缩。
/* webpack.prod.js */const ImageminPlugin = require("imagemin-webpack-plugin").default;const imageminMozjpeg = require("imagemin-mozjpeg");插件: [ new ImageminPlugin({test: /.(jpe?g|png|gif|svg)$/i,gifsicle: { // 无损 gif 压缩器 optimizationLevel: 9,},pngquant: { // 有损 png 压缩器,移除默认无损quality: "75",},plugins: [ imageminMozjpeg({// 有损 jpg 压缩器,删除默认无损quality: "75", }),], }),];
在这里,我们正在测试所有常见的字体扩展,并再次使用文件加载器来解析我们的字体导入并输出它们。
/* webpack.common.js */{ 测试:/.(woff|woff2|ttf|otf)$/, use: [{loader: '文件加载器',options: { name: '[name].[ext]', outputPath: 'fonts/', publicPath: 'fonts/'}, }]},
在我们的src/styles/base/_typography.scss
中,我们通过@font-face
规则加载字体。 Google Webfonts Helper 也是一个出色的工具,可以轻松自托管 Google Fonts。阅读有关 CSS-tricks 的@font-face
规则的更多信息。此外,还要阅读 font-display 属性。
预加载字体始终是最佳实践。我们将使用 preload-webpack-plugin 来实现这一点,并且您需要将其放在HtmlWebpackPlugin
之后才能正常工作。
/* webpack.common.js */new PreloadWebpackPlugin({ rel: '预加载', as(entry) {if (/.(woff|woff2|ttf|otf)$/.test(entry)) return '字体'; }, 文件白名单:[/.(woff|woff2|ttf|otf)$/], 包括:'所有资产'}),
在这里,我们回到webpack.prod.js
配置中,使用compression-webpack-plugin仅压缩 html、css 和 javascript 文件。这是为了避免压缩生成的源映射文件。
/* webpack.prod.js */module.exports = merge(common, { 模式:“生产”, plugins: [new CompressionPlugin({ test: /.(html|css|js)(?.*)?$/i // 仅压缩 html/css/js,跳过压缩源映射等}),});
Clean-webpack-plugin 只是一个简单的 webpack 插件,用于在构建新文件夹之前删除/清理构建文件夹。运行npm run build
或npm start
时观察文件夹结构。您当前的dist
文件夹(如果您之前构建过)将被删除,并且紧接着会出现一个新文件夹。
/* webpack.common.js */const CleanWebpackPlugin = require("clean-webpack-plugin");plugins: [new CleanWebpackPlugin(["dist"])];
使用源映射对于在开发工具中调试代码至关重要。
正如您所看到的,当您在 Chrome 中npm start
并打开 devtools 然后单击控制台时,您将看到有两个 console.log 来自script.js
第 1 行和第 2 行。我们可以在文件夹结构中轻松看到这一点src/scripts/script.js
。如果我们不使用 sourcemaps,那么 devtools 会向我们显示这些 console.logs 来自我们捆绑的webpack-bundle.js
,这不是很有帮助。
与我们的风格类似。如果您查看 devtools 中的body
元素,您会看到一些样式是从我们的_global.scss
文件应用的,还有一些是从我们的_typography.scss
文件应用的,它们都位于我们的src/styles/base/
文件夹中。如果我们忽略源映射,我们将无法知道这一点。它只会向我们显示来自捆绑的webpack-bundle.css
样式。
/* webpack.dev.js */module.exports = merge(common, { 模式:“开发”, devtool: "内联源映射",});
/* webpack.prod.js */module.exports = merge(common, { 模式:“生产”, devtool: "源映射",});
详细了解不同类型的源映射,找到最适合您的项目的源映射。另外,请阅读 webpack 文档中的 devtool 选项。
这是一个很棒的插件,可以根据一个图像源生成您需要的每个图标。在我的src/images/
文件夹中,我有一个tris-package.svg
,我将其输入到 favicons-webpack-plugin 中。
它将生成苹果、安卓、chrome、firefox、twitter、windows 的图标,凡是你能想到的。它将生成各种不同尺寸的每个图标,并将它们直接导入到它们所属的网站头部。 Twitter 和 windows 设置为 false 但默认,所以我将它们更改为 true 只是为了覆盖所有基础以防万一。
注意:这会大大增加构建时间。考虑到它在后台做了多少工作以及从长远来看它为您节省了多少时间,这是可以理解的。如果您的npm run build
比平时多花 20 秒,请不要感到惊讶。
/* webpack.prod.js */const FaviconsWebpackPlugin = require("favicons-webpack-plugin");module.exports = merge(common, { 模式:“生产”, 插件:[new FaviconsWebpackPlugin({ logo: "./src/images/favicon.svg", 图标: {twitter: true,windows: true, },}), ],});
在这里,我们使用离线插件插件来缓存页面加载时的所有资源。
该插件旨在为webpack项目提供离线体验。它使用ServiceWorker和AppCache作为幕后的后备。我们只需将此插件包含在我们的webpack.prod.js
中,并将附带的运行时包含在我们的客户端脚本 (src/index.js) 中,我们的项目将通过缓存所有(或部分)webpack 输出资源来离线准备。
注意:如果您npm run build
并将更改上传到您的服务器(或者您保持网站更新),则您的网站将需要关闭并重新打开才能看到更改。您无法打开它并保持刷新,您需要关闭选项卡并重新打开它以使缓存失效。
/* webpack.prod.js */const OfflinePlugin = require("offline-plugin");module.exports = merge(common, { 模式:“生产”, 插件:[new OfflinePlugin()],});
渐进式 Web 应用程序 (PWA) 是像常规网页或网站一样加载的 Web 应用程序,但可以为用户提供脱机工作、推送通知和传统上仅适用于本机应用程序的设备硬件访问等功能。 PWA 将网络的灵活性与本机应用程序的体验结合起来。
使此样板成为 PWA 的最后一步是将强制性的 Web 应用程序清单添加到项目的根目录并进行适当的配置!
当尝试捆绑像 jQuery 这样的大型库时,Webpack 会遇到问题。您最终会遇到控制台错误,例如$ is not defined
或jQuery is not defined
。为了解决这个问题,我们让 Webpack 将其视为外部。然后我们定义变量并通过 CDN 包含 jQuery。无论如何,大多数人都在浏览器上缓存了 jQuery,因此这不会成为性能问题。我默认添加了externals:
config,但是如果你打算使用它,你必须自己添加 jQuery cdn。
在 Webpack 文档中阅读有关外部的更多信息。
/* webpack.common.js */plugins: [],externals: { $: 'jquery', jquery: 'jQuery', '窗口.$': 'jquery',}
/* src/index.html */<head> <scriptdefersrc="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js" ></script></head>
我尽力彻底解释事情,但如果可以更清楚地解释某些事情,请随时发送带有一些建议编辑的拉取请求。谢谢你!
希望这有帮助!如果您对此感兴趣,请在 Twitter 上关注我。 ?