基础库分离

html-webpack-externals-plugin

  • 思路:将react、react-dom 基础包通过cdn引入,不打入bundle中
  • 方法:使用html-webpack-externals-plugin
    • 下载包:npm i html-webpack-externals-plugin -D
  1. // webpack.prod.js
  2. 'use strict';
  3. const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
  4. module.exports = {
  5. plugins: [
  6. new HtmlWebpackExternalsPlugin({
  7. externals: [
  8. {
  9. module: 'react',
  10. entry: 'https://unpkg.com/react@17/umd/react.production.min.js',
  11. global: 'React'
  12. },
  13. {
  14. module: 'react-dom',
  15. entry: 'https://unpkg.com/react-dom@17/umd/react-dom.production.min.js',
  16. global: 'ReactDOM'
  17. }
  18. ]
  19. })
  20. ],
  21. mode: 'production',
  22. }

SplitChunksPlugin

  • webpack4内置的,代替CommonsChunkPlugin插件
  • chunks参数说明
    • async:异步引入的库进行分离(默认)
    • initial:同步引入的库进行分离
    • all:所有引入的库进行分离 ```javascript // webpack.prod.js ‘use strict’; const path = require(‘path’); const glob = require(‘glob’); const HtmlWebpackPlugin = require(“html-webpack-plugin”);

const setMPA = () => { const entry = {}; const htmlWebpackPlugins = []; const entryFiles = glob.sync(path.join(__dirname, ‘./src//index.js’)); Object.keys(entryFiles).map(item => { const entryFile = entryFiles[item]; const match = entryFile.match(/.src\/(.)\/index.js/); const pageName = match && match[1]; entry[pageName] = entryFile;

  1. htmlWebpackPlugins.push(
  2. new HtmlWebpackPlugin({
  3. template: path.join(__dirname, `src/${pageName}/index.html`),
  4. filename: `${pageName}.html`,
  5. // 抽离出react和react-dom后,需要给htmlWebpackPlugin的chunks添加对应文件名
  6. chunks: ['vendors', pageName],
  7. inject: true,
  8. minify: {
  9. html5: true,
  10. collapseWhitespace: true,
  11. preserveLineBreaks: false,
  12. minifyCSS: true,
  13. minifyJS: true,
  14. removeComments: false
  15. }
  16. })
  17. )

}) return { entry, htmlWebpackPlugins, } }

const { entry, htmlWebpackPlugins } = setMPA();

module.exports = { plugins: [

].concat(htmlWebpackPlugins), optimization: { splitChunks: { cacheGroups: { common: { // 匹配import的时候的名称 test: /(react|react-dom)/, // 打包出的文件的命名 name: ‘vandors’, chunks: ‘all’ } } }, }, mode: ‘production’, }

  1. <a name="rG336"></a>
  2. # 代码分割
  3. - 意义:对于大的Web应用,将所有的代码都放在一个文件中显然是不够有效的,特别是当某些代码块是在某些特殊时候才会用到的。
  4. - webpack有个功能就是将代码库分割成 chunks (语块),当代码运行到需要他们的时候再进行加载
  5. - 使用场景
  6. - 抽离相同的代码到一个共享块
  7. - 脚本懒加载,使得初始下载的代码更小
  8. <a name="Kz1Ig"></a>
  9. ## 懒加载JS的方式
  10. - CommonJS:`require.ensure`
  11. - ES6:动态import (目前没有原生支持,需要babel转换)
  12. - 下载包:`npm i @babel/plugin-syntax-dynamic-import -D`
  13. > 目录结构
  14. > |-app
  15. > |-node_modules
  16. > |-.babelrc
  17. > |-package.json
  18. > |-webpack.prod.js
  19. > |-src
  20. > |-page
  21. > |-index
  22. > |-index.html
  23. > |-index.js
  24. > |-index.css
  25. > |-text.js
  26. > |-search
  27. > |-static
  28. > |-index.html
  29. > |-index.js
  30. > |-search.css
  31. ```javascript
  32. // src/page/index/index.js
  33. import { hello } from "./hello";
  34. document.write(hello());
  35. document.getElementById('btn').onclick = () => {
  36. import('./text.js').then((text) => {
  37. document.getElementById('text').innerHTML = text.default();
  38. })
  39. }
  1. // .babelrc
  2. {
  3. "presets": [
  4. "@babel/preset-env",
  5. "@babel/preset-react"
  6. ],
  7. "plugins": ["@babel/plugin-syntax-dynamic-import"]
  8. }
  1. 'use strict';
  2. const path = require('path');
  3. const glob = require('glob');
  4. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  5. const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
  6. const HtmlWebpackPlugin = require("html-webpack-plugin");
  7. const { CleanWebpackPlugin } = require('clean-webpack-plugin');
  8. const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
  9. const setMPA = () => {
  10. const entry = {};
  11. const htmlWebpackPlugins = [];
  12. const entryFiles = glob.sync(path.join(__dirname, './src/page/*/index.js'));
  13. Object.keys(entryFiles).map(item => {
  14. const entryFile = entryFiles[item];
  15. const match = entryFile.match(/.src\/page\/(.*)\/index.js/);
  16. const pageName = match && match[1];
  17. entry[pageName] = entryFile;
  18. htmlWebpackPlugins.push(
  19. new HtmlWebpackPlugin({
  20. template: path.join(__dirname, `src/page/${pageName}/index.html`),
  21. filename: `${pageName}.html`,
  22. // 抽离出react和react-dom后,需要给htmlWebpackPlugin的chunks添加对应文件名
  23. chunks: ['vendors', pageName],
  24. inject: true,
  25. minify: {
  26. html5: true,
  27. collapseWhitespace: true,
  28. preserveLineBreaks: false,
  29. minifyCSS: true,
  30. minifyJS: true,
  31. removeComments: false
  32. }
  33. })
  34. )
  35. })
  36. return {
  37. entry,
  38. htmlWebpackPlugins,
  39. }
  40. }
  41. const { entry, htmlWebpackPlugins } = setMPA();
  42. module.exports = {
  43. entry: entry,
  44. output: {
  45. path: path.join(__dirname, 'dist'),
  46. filename: '[name]_[chunkhash:8].js',
  47. },
  48. module: {
  49. rules: [
  50. {
  51. test: /\.js$/,
  52. use: 'babel-loader',
  53. },
  54. {
  55. test: /\.css$/,
  56. use: [MiniCssExtractPlugin.loader, 'css-loader']
  57. },
  58. {
  59. test: /\.less$/,
  60. use: [
  61. MiniCssExtractPlugin.loader,
  62. 'css-loader',
  63. 'less-loader',
  64. {
  65. loader: 'postcss-loader',
  66. options: {
  67. postcssOptions: { plugins: [['postcss-preset-env']] },
  68. }
  69. },
  70. {
  71. loader: 'px2rem-loader',
  72. options: {
  73. remUnit: 75,
  74. remPrecision: 8
  75. }
  76. }
  77. ],
  78. },
  79. {
  80. test: /\.(scss|sass)$/,
  81. use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
  82. },
  83. {
  84. test: /\.(png|jpg|gif|jpeg|svg)$/,
  85. use: [{
  86. loader: 'file-loader',
  87. options: {
  88. name: 'img/[name]_[hash:8].[ext]'
  89. }
  90. }]
  91. },
  92. {
  93. test: /\.(woff|woff2|eot|ttf|otf)$/,
  94. use: [{
  95. loader: 'file-loader',
  96. options: {
  97. name: 'fonts/[name]_[hash:8].[ext]'
  98. }
  99. }]
  100. }
  101. ]
  102. },
  103. plugins: [
  104. new MiniCssExtractPlugin({
  105. filename: '[name]_[contenthash:8].css'
  106. }),
  107. new CssMinimizerPlugin(),
  108. new CleanWebpackPlugin(),
  109. ].concat(htmlWebpackPlugins),
  110. optimization: {
  111. splitChunks: {
  112. cacheGroups: {
  113. common: {
  114. test: /(react|react-dom)/,
  115. name: 'vandors',
  116. chunks: 'all'
  117. }
  118. }
  119. },
  120. },
  121. mode: 'production',
  122. }

懒加载react

  • 会有问题,不会解决