贵阳网站建设是什么意思,有没有做英语试题的网站,asp网站密码,做百度推广网站得多少钱我们已经了解了许多关于 Webpack 的知识#xff0c;但要完全熟练掌握它并非易事。一个很好的学习方法是通过实际项目练习。当我们对 Webpack 的配置有了足够的理解后#xff0c;就可以尝试重构一些项目。本次我选择了一个纯HTML/JS的PC项目进行重构#xff0c;项目位于 GitH…我们已经了解了许多关于 Webpack 的知识但要完全熟练掌握它并非易事。一个很好的学习方法是通过实际项目练习。当我们对 Webpack 的配置有了足够的理解后就可以尝试重构一些项目。本次我选择了一个纯HTML/JS的PC项目进行重构项目位于 GitHub 上非常感谢该项目的贡献者。
重构案例选择了两个页面首页 index.html 和购物车页面 cart.html。 项目目录结构清晰根目录包含了各个 HTML 页面同一层级下还有 CSS、JS 和 IMG 文件夹。每个 HTML 页面对应各自的 CSS 和业务 JS 文件。 初始化 npm 项目
首先创建一个新的空文件夹并在其中运行 npm init -y 命令来初始化项目。接着在项目根目录下创建 src 文件夹将 index.html 文件复制到 src 目录下以此为基础进行重构。打开 index.html 文件可以看到页面中引入了 CSS、图片和 JS 资源。然后将 CSS、IMG 和 JS 文件夹也移至 src 目录下。 随后我们观察 index.html 文件中的 link 和 script 标签它们分别用于加载外部的 CSS 文件和 JavaScript 文件。为了使项目更好地适应 Webpack 的模块化打包机制在 index.html 同一目录级别的位置创建一个新的 index.js 文件。在这个新的 index.js 文件中我们将使用模块化的方式导入原本通过 link 标签引入的 CSS 文件以及通过 script 标签加载的 JavaScript 文件。
对于那些直接嵌入在 script 标签内的脚本代码例如图中提到的 flexslider 函数我们暂且保持其原样不做变动。
import ./css/public.css;
import ./css/index.css;import ./js/jquery-1.12.4.min.js
import ./js/public.js;
import ./js/nav.js;
import ./js/jquery.flexslider-min.js;初始化 webpack
使用命令 npm install webpack --save 来安装 Webpack并创建 webpack.config.js 文件来定义基本的配置。由于原项目包含多个 HTML 页面因此这是一个多入口项目。
const path require(path);
module.exports {mode: development,entry: {index: ./src/index.js,},output: {filename: [name].[hash:8].js,path: path.join(__dirname, ./dist),},
};在 package.json 中添加 build: webpack 命令。
处理css、图片
Webpack 默认不支持处理 CSS 和图片资源。要处理 CSS 资源可以通过 css-loader 和 style-loader而图片资源则可以通过 Webpack 5 的内置功能——asset module 来处理。
首先安装处理 CSS 所需的依赖项
npm install css-loader style-loader --save这里我们使用 css-loader 来解析 CSS 文件并通过 style-loader 将其作为内联样式插入到 DOM 中。初期阶段我们可以先这样创建内联样式之后再考虑将 CSS 资源进一步抽离优化。
module.exports {module: {rules: [{ test: /\.css$/, use: [style-loader, css-loader] },{ test: /\.(jpg|jpeg|png|gif|svg)/i, type: asset },],},
}处理 html
使用 html-webpack-plugin 插件根据 index.html 创建压缩后的 HTML 文件并将编译后的 JS 文件引入。
const HtmlWebpackPlugin require(html-webpack-plugin);module.exports {plugins: [new HtmlWebpackPlugin({template: ./src/index.html,filename: index.html,}),],
}图片资源
asset module 主要用于处理在 CSS 文件中通过背景图像或其他方式引入的图片资源。然而对于 HTML 页面中直接通过标签引入的资源它则无能为力。 如图所示这些图片的路径都是 img/xxx.png。由于编译后的文件位于 dist 文件夹下而此时 dist 文件夹下没有 img 目录。因此我们可以通过 copy-webpack-plugin 将 src 目录下的 img 文件夹复制到 dist 目录下。
const CopyPlugin require(copy-webpack-plugin);module.exports {plugins: [new CopyPlugin({patterns: [{from: ./src/img,to: ./img,},],}),],
};这样一来当我们执行 npm run build 时dist 文件夹中已经生成了 index.html 及其对应的 CSS、JS 和图片等资源。然而当我们尝试从 index.html 打开页面时却发现页面报错提示 $ 未定义并且页面底部定义的 flexslider 方法并未生效。 ProvidePlugin $ 符号
我们知道 $ 符号实际上是 jQuery 提供的一个全局变量。提示找不到 $ 符意味着 jQuery 的全局变量尚未正确暴露。为了解决这个问题我们可以按照以下步骤操作
首先通过安装 jQuery
npm install jquery --save接着调整 index.js 文件中的引入方式
// 修改前
import ./js/jquery-1.12.4.min.js// 修改后
import jquery;然后使用 ProvidePlugin 来定义 $ 的映射关系
const webpack require(webpack);
module.exports {plugins: [new webpack.ProvidePlugin({$: jquery,jQuery: jquery,}),],
};最后将 index.html 文件底部通过 script 标签调用的 flexslider 函数代码移动到需要引入的业务 JS 文件中。
完成上述步骤后再次执行 npm run build原有的 index.html 功能就能实现基本的重构接下来就可以进行更多的优化工作了。
自动清空编译后文件夹
在执行 npm run build 时Webpack 会根据 webpack.config.js 中的规则在 dist 目录下生成编译后的文件。为了避免 dist 文件夹中生成的文件混杂在一起通常我们需要在每次编译前手动清理该目录。
为了省去这一手动操作的麻烦我们可以使用 clean-webpack-plugin 来自动清空 dist 文件夹。这样可以确保每次构建时dist 目录都是干净的从而避免旧文件的干扰。
const { CleanWebpackPlugin } require(clean-webpack-plugin);
module.exports {plugins: [new CleanWebpackPlugin()],
};抽离css文件
这样会导致 JS 文件体积过大并且 JS 和 CSS 代码混合在一起不够清晰。在开发环境中这种方式是可行的因为编译速度快但在生产环境中我们需要将 CSS 资源抽离成单独的文件。 为此我们可以使用 mini-css-extract-plugin 替换掉 style-loader以实现 CSS 资源的独立打包。
const MiniCssExtractPlugin require(mini-css-extract-plugin);module.exports {module: {rules: [{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, css-loader] },],},plugins: [new MiniCssExtractPlugin({filename: [name].[hash:8].css,chunkFilename: [name].[hash:8].css,}),],
};通过这种方式CSS 资源会被单独打包成一个文件从而使得最终的输出更加规范和高效。如图所示CSS 文件已经被独立出来。 js和css压缩
在前面的配置中mode 被设置为 development这在开发模式下便于调试。然而在代码发布时我们需要切换到 production 模式。在这种模式下Webpack 会自动对资源文件进行压缩以减小文件大小。
除了更改 mode 设置之外我们还可以利用 terser-webpack-plugin 和 css-minimizer-webpack-plugin 分别对 JavaScript 和 CSS 资源进行进一步的压缩。
const TerserPlugin require(terser-webpack-plugin);
const CssMinimizerWebpackPlugin require(css-minimizer-webpack-plugin);module.exports {mode: production,optimization: {minimizer: [new TerserPlugin({}), new CssMinimizerWebpackPlugin()],},
};如图所示我们可以看到不同 mode 设置下以及使用插件对代码资源进行压缩后的文件体积变化。尽管当前项目只有一个页面包含少量的 HTML、CSS 和 JS 文件因此代码压缩的效果可能不是特别显著但随着项目规模的扩大这种压缩策略的效果将更加明显。 增加开发模式
以上代码的修改我们都通过执行 npm run build 来观察编译后的产物。然而当需要迁移多个文件时使用开发模式会更便于实时查看所有业务场景的使用情况。
为了实现这一点我们可以使用 webpack-dev-server 来启动一个开发服务器。安装完成后在 webpack.config.js 文件中增加 devServer 的配置
module.exports {devServer: {open: true,compress: true,port: 8000,},
};接着在 package.json 文件中配置一个用于启动开发服务器的脚本指令
scripts: {
dev: webpack serve,
},这样一来通过执行 npm run dev 即可启动开发服务器并自动打开浏览器查看 index.html 页面的内容。这样不仅方便调试还能实时预览代码改动的效果。
多入口
到目前为止我们仅迁移了首页的资源。现在我们将继续迁移购物车页面。与首页的迁移类似首先将 cart.html 文件复制到 src 目录下并查找其中引入的 CSS 和 JS 资源。 接着创建一个 cart.js 文件并在其中引入所需的 JS 和 CSS 文件
// cart.js
import ./css/public.css;
import ./css/proList.css;import jquery;
import ./js/public.js;
import ./js/pro.js;
import ./js/cart.js;接下来的配置非常关键。我们需要在 webpack.config.js 中定义多入口并为每个页面生成相应的模板 HTML 文件。这里需要注意的是一定要定义 chunks 属性否则生成的 HTML 页面会错误地引入所有 CSS 和 JS 文件。
module.exports {entry: {index: ./src/index.js,cart: ./src/cart.js,},plugins: [new HtmlWebpackPlugin({template: ./src/index.html,filename: index.html,chunks: [index],}),new HtmlWebpackPlugin({template: ./src/cart.html,filename: cart.html,chunks: [cart],}),],
};完成上述配置后再次执行 npm run build即可编译出两个页面。此时在 dist 文件夹中直接点击 cart.html 文件也可以顺利访问页面内容。
拆分公共资源
尽管目前可以编译出两个 HTML 页面的资源但如果查看 dist 文件夹下的 index.js 或者 cart.js 文件会发现里面仍然包含有 jQuery 的代码。 为了优化这种情况我们希望将像 jQuery 这样的重复资源作为公共模块来引用而不是让它们在不同的 JS 文件中反复编译。以下是一个详细的 splitChunks 配置示例它可以将 node_modules 中的资源进行分类处理将 jQuery 编译成单独的文件并将其他第三方库编译为另一个文件。
module.exports {optimization: {splitChunks: {chunks: all,name: common,cacheGroups: {jquery: {// 测试模块是否包含 jquery 字符串test: /[\\/]node_modules[\\/]jquery[\\/]/,// 设置文件名name: jquery,// 文件名可以是函数形式也可以直接指定字符串filename: jquery.js,// 确保只包含异步加载的 chunk 中的 jQuerypriority: 10, // 可以设置优先级来控制合并顺序enforce: true, // 强制创建这个 chunk 即使其他规则可能忽略它},vendors: {// 这个 cache group 用来处理其他第三方库test: /[\\/]node_modules[\\/]/,name: vendors,priority: -10,filename: vendors.js,chunks: all,},},},},
};由于当前项目中只用到了 jQuery 这一资源因此只有 jQuery 被单独打包。随着项目发展和资源的增加可以进一步细化拆分规则。从结果可以看出当 jQuery 被拆分出来后index.js 和 cart.js 的文件体积都有了显著的减少。 模板文件ejs
在不同的页面中页面顶部的导航通常是固定且相同的。在当前项目中相同的 HTML 部分是通过复制来定义的。为了提高代码的复用性和维护性我们可以使用 EJSEmbedded JavaScript来将这部分相同的逻辑抽离出来。 首先在 src 文件夹下创建一个 ejs 文件夹并在其中创建一个 header.ejs 文件。找到定义 header 的代码将其复制到 header.ejs 文件中并将变化的内容如页面标题通过 % title % 的方式定义。
然后在原来 HTML 页面中定义 header 代码的地方引入 header.ejs 文件并传入动态变量
%require(./ejs/header.ejs)({ title: 首页})%由于 Webpack 本身不具备处理 EJS 文件的能力因此我们需要安装 ejs-loader 并配置相应的处理规则
module.exports {module: {rules: [{ test: /\.ejs/, loader: ejs-loader, options: { esModule: false } },],},
};通过这样的配置我们就实现了公共代码的复用。
以上步骤完成了从纯 HTML/JS 项目迁移到使用 Webpack 进行开发的全过程。通过使用 Webpack我们实现了代码分割、资源按需加载并采用了模块化开发。借助 html-webpack-plugin 和 clean-webpack-plugin 等插件简化了构建流程确保每次构建都能得到干净且优化的输出文件。
通过 EJS 抽象公共头部等重复代码片段减少了冗余提高了代码复用率使代码库更简洁。
如果你对前端、JavaScript 和工程化感兴趣快来瞅瞅我的其他文章吧我会不定期分享各种学习心得和使用技巧。戳我的头像一起探索更多好玩的内容吧