经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
webpack4 系列教程(十六):开发模式和生产模式·实战
来源:cnblogs  作者:GodBMW  时间:2018/10/22 16:24:49  对本文有异议

作者按:这是webpack4系列最后一篇教程了。这篇文章在之前所有教程的基础上,做了一个真正意义上的 webpack 项目!我花费了三个月整理了这份教程,并且完善了相关示例代码,也更熟悉 webpack 的理论和应用,当然,也感谢大家的支持。好了,感慨完毕,开始正题 ??

0. 课程介绍和资料

本节课的代码目录如下:

1. 如何分离开发环境和生产环境?

熟悉 Vuejs 或者 ReactJs 的脚手架的朋友应该都知道:在根目录下有一个/build/文件夹,专门放置webpack配置文件的相关代码。

不像我们前 15 节课的 demo (只有一个配置文件webpack.config.js),为了分离开发环境和生产环境,我们需要分别编写对应的webpack配置代码。

毫无疑问,有一些插件和配置是两种环境共用的,所以应该提炼出来,避免重复劳动。如前文目录截图,build/webpack.common.conf.js就保存了两种环境都通用的配置文件。而build/webpack.dev.conf.jsbuild/webpack.prod.conf.js分别是开发和生产环境需要的特殊配置。

2. 编写package.json

类似上一节讲的,为了让命令更好调用,需要配置scripts选项。模仿vue-cli的命令格式,编写如下package.json:

  1. {
  2. "scripts": {
  3. "dev": "webpack-dev-server --env development --open --config build/webpack.common.conf.js",
  4. "build": "webpack --env production --config build/webpack.common.conf.js"
  5. },
  6. "devDependencies": {
  7. "babel-core": "^6.26.3",
  8. "babel-loader": "^7.1.5",
  9. "babel-plugin-transform-runtime": "^6.23.0",
  10. "babel-preset-env": "^1.7.0",
  11. "clean-webpack-plugin": "^0.1.19",
  12. "css-loader": "^1.0.0",
  13. "extract-text-webpack-plugin": "^4.0.0-beta.0",
  14. "html-webpack-plugin": "^3.2.0",
  15. "jquery": "^3.3.1",
  16. "style-loader": "^0.21.0",
  17. "webpack": "^4.16.1",
  18. "webpack-cli": "^3.1.0",
  19. "webpack-dev-server": "^3.1.4",
  20. "webpack-merge": "^4.1.3"
  21. },
  22. "dependencies": {
  23. "babel-polyfill": "^6.26.0",
  24. "babel-runtime": "^6.26.0"
  25. }
  26. }

按照配置,运行:

  • npm run dev: 进入开发调试模式
  • npm run build: 生成打包文件

还可以看出来,build/webpack.common.conf.js不仅仅是存放着两种环境的公共代码,还是webpack命令的入口文件。

3. 如何合并 webpack 的不同配置?

根据前面所讲,我们有 3 个配置文件。那么如何在build/webpack.common.conf.js中引入开发或者生产环境的配置,并且正确合并呢?

此时需要借助webpack-merge这个第三方库。下面是个示例代码:

  1. const merge = require("webpack-merge");
  2. const productionConfig = require("./webpack.prod.conf");
  3. const developmentConfig = require("./webpack.dev.conf");
  4. const commonConfig = {}; // ... 省略
  5. module.exports = env => {
  6. let config = env === "production" ? productionConfig : developmentConfig;
  7. return merge(commonConfig, config); // 合并 公共配置 和 环境配置
  8. };

4. 如何在代码中区分不同环境?

4.1 配置文件

如果这个 js 文件是 webpack 命令的入口文件,例如build/webpack.common.conf.js,那么mode的值(production 或者 development)会被自动传入module.exports的第一个参数,开发者可以直接使用。

如下面的代码,先判断是什么环境,然后再决定使用什么配置,最后 return 给 webpack:

  1. module.exports = env => {
  2. let config = env === "production" ? productionConfig : developmentConfig;
  3. return merge(commonConfig, config); // 合并 公共配置 和 环境配置
  4. };

4.2 项目文件

如果这个 js 文件是项目中的脚本文件,那么可以访问process.env.NODE_ENV这个变量来判断环境:

  1. if (process.env.NODE_ENV === "development") {
  2. console.log("开发环境");
  3. } else {
  4. console.log("生产环境");
  5. }

5. 编写配置文件

5.1 编写公共配置文件

  1. // /build/webpack.common.conf.js
  2. const webpack = require("webpack");
  3. const merge = require("webpack-merge");
  4. const ExtractTextPlugin = require("extract-text-webpack-plugin");
  5. const HtmlWebpackPlugin = require("html-webpack-plugin");
  6. const path = require("path");
  7. const productionConfig = require("./webpack.prod.conf.js"); // 引入生产环境配置文件
  8. const developmentConfig = require("./webpack.dev.conf.js"); // 引入开发环境配置文件
  9. /**
  10. * 根据不同的环境,生成不同的配置
  11. * @param {String} env "development" or "production"
  12. */
  13. const generateConfig = env => {
  14. // 将需要的Loader和Plugin单独声明
  15. let scriptLoader = [
  16. {
  17. loader: "babel-loader"
  18. }
  19. ];
  20. let cssLoader = [
  21. {
  22. loader: "css-loader",
  23. options: {
  24. minimize: true,
  25. sourceMap: env === "development" ? true : false // 开发环境:开启source-map
  26. }
  27. }
  28. ];
  29. let styleLoader =
  30. env === "production"
  31. ? ExtractTextPlugin.extract({
  32. // 生产环境:分离、提炼样式文件
  33. fallback: {
  34. loader: "style-loader"
  35. },
  36. use: cssLoader
  37. })
  38. : // 开发环境:页内样式嵌入
  39. cssLoader;
  40. return {
  41. entry: { app: "./src/app.js" },
  42. output: {
  43. publicPath: env === "development" ? "/" : __dirname + "/../dist/",
  44. path: path.resolve(__dirname, "..", "dist"),
  45. filename: "[name]-[hash:5].bundle.js",
  46. chunkFilename: "[name]-[hash:5].chunk.js"
  47. },
  48. module: {
  49. rules: [
  50. { test: /\.js$/, exclude: /(node_modules)/, use: scriptLoader },
  51. { test: /\.css$/, use: styleLoader }
  52. ]
  53. },
  54. plugins: [
  55. // 开发环境和生产环境二者均需要的插件
  56. new HtmlWebpackPlugin({
  57. filename: "index.html",
  58. template: path.resolve(__dirname, "..", "index.html"),
  59. chunks: ["app"],
  60. minify: {
  61. collapseWhitespace: true
  62. }
  63. }),
  64. new webpack.ProvidePlugin({ $: "jquery" })
  65. ]
  66. };
  67. };
  68. module.exports = env => {
  69. let config = env === "production" ? productionConfig : developmentConfig;
  70. return merge(generateConfig(env), config);
  71. };

5.2 编写开发环境配置文件

  1. // /build/webpack.dev.conf.js
  2. const webpack = require("webpack");
  3. const path = require("path");
  4. module.exports = {
  5. mode: "development",
  6. devtool: "source-map",
  7. devServer: {
  8. contentBase: path.join(__dirname, "../dist/"),
  9. port: 8000,
  10. hot: true,
  11. overlay: true,
  12. proxy: {
  13. "/comments": {
  14. target: "https://m.weibo.cn",
  15. changeOrigin: true,
  16. logLevel: "debug",
  17. headers: {
  18. Cookie: ""
  19. }
  20. }
  21. },
  22. historyApiFallback: true
  23. },
  24. plugins: [
  25. new webpack.HotModuleReplacementPlugin(),
  26. new webpack.NamedModulesPlugin()
  27. ]
  28. };

5.3 编写生产环境配置文件

  1. // /build/webpack.comm.conf.js
  2. const ExtractTextPlugin = require("extract-text-webpack-plugin");
  3. const CleanWebpackPlugin = require("clean-webpack-plugin");
  4. const path = require("path");
  5. module.exports = {
  6. mode: "production",
  7. plugins: [
  8. new ExtractTextPlugin({
  9. filename: "[name].min.css",
  10. allChunks: false // 只包括初始化css, 不包括异步加载的CSS
  11. }),
  12. new CleanWebpackPlugin(["dist"], {
  13. root: path.resolve(__dirname, "../"),
  14. verbose: true
  15. })
  16. ]
  17. };

6. 其他文件

在项目目录截图中展示的样式文件,vendor 下的文件还有 app.js,代码就不一一列出了。完全可以根据自己的需要,写一些简单的代码,然后运行一下。毕竟前面的配置文件的架构和讲解才是最重要的。

这里仅仅给出源码地址(欢迎 Star 哦):

7. 运行效果和测试

鼓捣这么半天,肯定要测试下,要不怎么才能知道正确性(这才是另人激动的一步啦啦啦)。

7.1 跑起来:开发模式

进入项目目录,运行npm run dev:

成功跑起来,没出错(废话,都是被调试了好多次了哈哈哈)。

打开浏览器的控制台看一下:

很好,都是按照编写的app.js的逻辑输出的。

7.2 跑起来:生产模式

Ctrl+C退出开发模式后,运行npm run build,如下图打包成功:

打包后的文件也放在了指定的位置:

直接点击index.html,并且打开浏览器控制台:

ok, 符合app.js的输出:成功辨识了是否是开发环境!!!

8. 最终

完结撒花 ?? ヽ(°▽°)ノ ?

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号