От основ к реальному бою

внешний интерфейс Webpack

адрес проектаGitHub.com/Непобедимый НЛО/Интернет…

Обзор точек знаний:

Загрузчик, HMR, создание приложения React, кэширование, Плагин, SourceMap, Vue Cli 3.0, Shimming, WebpackDevServer, TreeShaking, CodeSplitting, Babel, React, Library, Eslint, PWA, Vue, Mode, оптимизация производительности, многостраничное приложение, принцип, Предварительная загрузка, предварительная выборка, переменные среды, TypeScript

награда:

Тщательно изучите конфигурацию Webpack Понять роль и принцип Webpack Настройка процесса упаковки стартап-проекта Иметь передовое инженерное мышление Вступите в ряды старших фронтенд-инженеров

1: Первое знакомство с Webpack

Официальный сайт карты городской застройки:

1.1 Что такое веб-пакет

webpackэто современное приложение JavaScriptИнструмент упаковки статических модулей: что он делает, так это анализирует структуру вашего проекта, находит модули JavaScript и другие языки расширения (Scss, TypeScript и т. д.), которые браузеры не могут запускать напрямую, и генерирует один или несколькоbundle, упакуйте его в формат, подходящий для браузера.

сборка вебпака:

Создание — это преобразование исходного кода в исполняемый код JavaScript, CSS и HTML, который публикуется в Интернете, включая следующие.

1. Преобразование кода: TypeScript компилируется в JavaScript, SCSS или Less компилируется в CSS и т. д.

2. Оптимизация файлов: сжатие JavaScript, CSS, HTML-кода, сжатие и объединение изображений и т. д.

3. Сегментация кода: извлеките общий код нескольких страниц и извлеките код, который не нужно выполнять на первом экране, чтобы загрузить его асинхронно.

4. Слияние модулей: в модульном проекте будет много модулей и файлов, и функция построения необходима для классификации и объединения модулей в один файл.

5. Автоматическое обновление: отслеживайте изменения локального исходного кода, автоматически перестраивайте, обновляйте браузер, nodemon.

6. Проверка кода. Перед отправкой кода на склад необходимо проверить, соответствует ли код спецификации и проходит ли модульный тест.

7. Автоматический выпуск: после обновления кода автоматически создается код онлайн-выпуска, который передается в систему выпуска.

Конструирование на самом деле является воплощением инженерии и автоматизации в разработке интерфейса.Серия процессов реализована в коде, и код может автоматически выполнять эту серию сложных процессов. Строительство придает больше жизненной силы фронтенд-разработке, высвобождает нашу производительность и делает нашу разработку более удобной.

1.2 Что такое модули веб-пакета

  • ES2015 importутверждение

  • CommonJS require()утверждение

  • AMD defineа такжеrequireутверждение

  • в файлах css/sass/less@importутверждение.

  • стиль(url(...)) или файл HTML (<img src=...>) ссылка на картинку

    Подробности смотрите в официальном документе на сайте:Modules MODULES

1.3 Создание среды Webpack

  • Перейти на официальный сайт для загрузкиnode

    // 查看node版本号
    node -v
    // 查看npm版本号
    npm -v
    

1.4 Инициализировать проект

mkdir webpack-productname
cd webpack-productname 
//初始化webpack配置清单package.json
npm init -y   

1.5 Установить веб-пакет

//全局安装(不推荐),因为如果有两个项目用了webpack不同版本,就会出现版本不统一运行不起来的情况。只有卸了当前版本安装对应版本非常麻烦。
npm install webpack webpack-cli -g
//查看版本
webpack -v
//全局卸载
npm uninstall webpack webpack-cli -g
//在项目里安装webpack(推荐使用)。可以在不同项目中使用不同的webpack版本。
cd webpack-productname
npm install webpack webpack-cli -D
//查看版本
npx webpack -v
//查看对应包的详细信息
npm info webpack
//安装指定版本包
npm install webpack@4.16.1 webpack-cli -D

Уведомление:

Поскольку npm устанавливается в чужой сети, он работает относительно медленно и подвержен сбоям при установке.

Вы можете установить его с помощью пряжи. Во-первых, вы должны установить пряжу глобально.npm install yarn -g.

Или используйте nrm для быстрого переключения источников npm, сначала установите nrm глобально,npm install -g nrm.

НРМ использует:

nrm ls для просмотра дополнительных источников.

nrm тест npm тест скорости. Посмотрите, какой из них быстро использовать.

nrm используйте cnpm Используйте cnpm.

webpack-cli: позволяет нам правильно использовать webpack из командной строки

1.6 конфигурационный файл веб-пакета

webpack работает из коробки без каких-либо файлов конфигурации. Однако webpack будет считать, что точка входа в проектsrc/index, затем вdist/main.jsВыведите результаты и включите сжатие и оптимизацию в рабочей среде. Обычно ваш проект нуждается в дальнейшем расширении этой возможности, для этого вы можете создатьwebpack.config.jsфайл, webpack будет использовать его автоматически.

Создан в корневом каталоге проектаwebpack.config.jsфайл, который является файлом конфигурации веб-пакета по умолчанию

const path = require('path')

module.exports = {
    //默认是production,打包的文件默认被压缩。开发时可以设置为development,不被压缩
    mode:'production', 
    //打包项目的入口文件
    entry: './index.js',
    //打包项目的输出文件
    output: {
        //自定义打包输出文件名
        filename:'bundle.js',
        //输出文件的绝对路径
        path: path.resolve(__dirname,'bundle')
    }
}

Вы также можете указать файл конфигурации самостоятельно, чтобы завершить упаковку веб-пакета:

npx webpack --config + 自定义配置文件

Подробности смотрите в официальной документации:концепция настроить

1.7 содержимое вывода упаковки webpack

执行 `npm run build` 后,在控制台输出

Hash:1b245e275a547956bf52 //本次打包对应唯一一个hash值
Version:webpack 4.29.6 //本次打包对应webpack版本
Time:162ms Built at:2019-4-11 23:13:43 //本次打包耗时,及打包的时间
Asset Size Chunks Chunk Names //打包后的文件名,大小,id,入口文件名
bundle.js 1.36 KiB 0 [emitted] main 
Entrypoint main=bundle.js
[0]./src/index.js 159 bytes {0}[built]
[1]./src/header.js 187 bytes {e}[built]
[2]./src/sidebar.js 193 bytes {e}[built]
[3]./src/content.js 193 bytes {e} [built]

Второе: основные концепции Webpack

LOADER

2.1 Что такое загрузчик

вебпак может использоватьloaderДля предварительной обработки файлов с помощью различных загрузчиков webpack может компилировать различные статические файлы в файлы js, такие как css, sass, less, ES6/7, vue, JSX и т. д.

Пакет погрузчика с использованием статических ресурсов

Поддержка загрузки файлов изображений:

необходимо установитьfile-loader: Решена проблема импорта путей к изображениям в CSS и других файлах.

 npm install file-loader -D

существуетwebpack.config.jsДобавьте конфигурацию загрузчика в

module.exports = {
    //配置模块,主要用来配置不同文件的加载器
  module: {
      //配置模块规则
    rules: [
      {
        test: /\.(png|jpg|gif)$/, //正则匹配要使用相应loader的文件
        use: [
          {
            loader: 'file-loader', //要用到的loader
              options: {
                  //palceholder占位符
                  name:'[name].[ext]', //打包后的图片名字,后缀和打包的之前的图片一样
                  outputPath: 'images/' //图片打包后的地址
              },
          },
        ],
      },
    ],
  },
};

Подробности смотрите в официальной документации:file-loader

Преобразование небольших изображений в формат base64

необходимо установитьurl-loader: Когда картинка меньше лимита, картинка будет закодирована в BASE64.Если больше лимита, для копирования будет использоваться файл-загрузчик.

npm install url-loader -D

существуетwebpack.config.jsДобавьте конфигурацию загрузчика в

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif|bmp/)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              name:'[name].[ext]',
              outputPath: 'images/',
              limit: 8192 //小于8192b,就可以转化成base64格式。大于就会打包成文件格式
            }
          }
        ]
      }
    ]
  }
}

Подробности смотрите в официальной документации:url-loader


Поддержка CSS-файла стиля загрузки:

необходимо установитьcss-loader style-loader:

npm install css-loader style-loader -D

существуетwebpack.config.jsДобавьте конфигурацию загрузчика в

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/, //匹配以css为后缀的文件
        use: ['style-loader', 'css-loader'],//loader的执行顺序是从右向左,从下到上。css-loader:分析几个css文件之间的关系,最终合并为一个css。style-loader:在得到css生成的内容时,把其挂载到html的head里,成为内联样式。
      },
    ],
  },
};

Поддержка загрузки стилей файлов SASS.:

необходимо установитьsass-loader node-sass:

npm install sass-loader node-sass -D

существуетwebpack.config.jsДобавьте конфигурацию загрузчика в

module.exports = {
    ...
    module: {
        rules: [{
            test: /\.scss$/,
            use: [
                "style-loader", // 将 JS 字符串生成为 style 节点
                "css-loader", // 将 CSS 转化成 CommonJS 模块
                "sass-loader" // 将 Sass 编译成 CSS,默认使用 Node Sass
            ]
        }]
    }
};

Префикс свойств стиля css для разных браузеров

Для совместимости с браузером иногда нам приходится добавлять эти префиксы -webkit,-ms,-o,-moz

  • Ядро Trident: в основном представлено браузером IE с префиксом -ms
  • Ядро Gecko: основным представителем является Firefox с префиксом -moz.
  • Ядро Presto: основной представитель Opera с префиксом -o
  • Ядро Webkit: основными продуктами являются Chrome и Safari с префиксом -webkit.
npm i postcss-loader autoprefixer -D

Создать в рамках проекта и каталогаpostcss.config.js

module.exports = {
    plugins: [
        require('autoprefixer')
    ]
}

webpack.config.js

module.exports = {
    ...
    module: {
        rules: [{
            test: /\.scss$/,
            use: [
                "style-loader", // 将 JS 字符串生成为 style 节点
                "css-loader", // 将 CSS 转化成 CommonJS 模块
                'postcss-loader',//配置在css-loader后,在sass|less|stylus-loader 之前。
                "sass-loader" // 将 Sass 编译成 CSS,默认使用 Node Sass
                
            ]
        }]
    }
};

Добавьте некоторые элементы конфигурации в загрузчик:

webpack.config.js

module.exports = {
    ...
    module: {
        rules: [{
            test: /\.scss$/,
            use: [
                "style-loader", 
                {
                 	loader: "css-loader",
                    options:{
                        importLoaders:2 ,//如果sass文件里还引入了另外一个sass文件,另一个文件还会从sass-loader向上解析。如果不加,就直接从css-loader开始解析。// 0 => no loaders (default); 1 => postcss-loader; 2 => postcss-loader, sass-loader
                        modules: true //开启css的模块打包。css样式不会和其他模块发生耦合和冲突
                    }
                }, 
                'postcss-loader',
                "sass-loader", 
                
            ]
        }]
    }
};

Настроить загрузчик для файла значка шрифта

существуетБиблиотека векторных иконок Alibaba, загрузите нужный значок шрифта на локальный диск и распакуйте его. Будуiconfont.eot iconfont.svg iconfont.ttf iconfont.woffПоместите файл в проект и создайте новую папку font в src, чтобы поместить значок шрифта. Скопируйте файл iconfont.css в проект и самостоятельно измените путь к значку импортированного шрифта.

необходимо установитьfile-loader:

npm i file-loader -D

webpack.config.js

module.exports = {
    ...
    module: {
        rules: [{
            test: /\.(eot|ttf|svg|woff)$/,
            use:{
                loader:'file-loader'
            }
        },
            ]
        }]
    }
};

Подробности смотрите в официальной документации:asset-management


плагин: может что-то сделать для вас, когда веб-пакет запускается до определенной точки

Используйте плагины, чтобы упростить упаковку

HtmlWebpackPlugin: htmlWebpackPlugin автоматически сгенерирует html-файл после упаковки и автоматически вставит упакованный js в этот html-файл.

Установить:npm i html-webpack-plugin -D

Основное использование: в webpack.config.js:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');

module.exports = {
  entry: 'index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index_bundle.js'
  },
    plugins: [new HtmlWebpackPlugin({
        template: 'src/index.html' //以index.html为模板,把打包生成的js自动引入到这个html文件中
    })]
};

CleanWebpackPlugin: автоматически очищать последний упакованный дистрибутивный файл.

Установить:npm i clean-webpack-plugin -D

Основное использование: в webpack.config.js:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');

module.exports = {
  entry: 'index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'index_bundle.js'
  },
    plugins: [
        new HtmlWebpackPlugin({
        template: 'src/index.html' //在打包之后,以.html为模板,把打包生成的js自动引入到这个html文件中
    }),
        new CleanWebpackPlugin(['dist']), // 在打包之前,可以删除dist文件夹下的所有内容
    
    ]
};

Базовая конфигурация входа и выхода

Конфигурация при упаковке файлов с несколькими входами

Основное использование: в webpack.config.js:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');

module.exports = {
  entry: {
   	main: './src/index.js',
    sub: './src/index.js'
  },
  output: {
    publicPath: 'http://cdn.com.cn', //将注入到html中的js文件前面加上地址
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  },
    plugins: [
        new HtmlWebpackPlugin({
        template: 'src/index.html' //在打包之后,以.html为模板,把打包生成的js自动引入到这个html文件中
    }),
        new CleanWebpackPlugin(['dist']), // 在打包之前,可以删除dist文件夹下的所有内容
    
    ]
};

Подробности смотрите на официальном сайте:Output output-management


Конфигурация SourceMap

sourcemap: отношение отображения между упакованными и скомпилированными файлами и исходными файлами используется для отладки разработчиком.

  • source-map генерирует файлы карт в отдельные файлы, наиболее полные, но самые медленные

  • Cheap-module-source-map создает карту без сопоставления столбцов в отдельном файле.

  • eval-source-map Используйте eval для упаковки модулей исходного файла и создания полной исходной карты в том же файле.

  • исходная карта cheap-module-eval-source-map и упакованные аналоги JS показывают, что нет столбца сопоставления

    Рекомендуется для среды разработки: devtool: 'cheap-module-eval-source-map', Рекомендуется для производственных сред: devtool: 'cheap-module-source-map',

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
	mode: 'development',
    devtool: 'cheap-module-eval-source-map',
	//devtool:'none',//在开发者模式下,默认开启sourcemap,将其关闭
    //devtool:'source-map'//开启映射打包会变慢
    //devtool:'inline-source-map'//不单独生成.map文件,会将生成的映射文件以base64的形式插入到打包后的js文件的底部
    //devtool:'cheap-inline-source-map'//代码出错提示不用精确显示第几行的第几个字符出错,只显示第几行出错,会提高一些性能
    //devtool:'cheap-module-inline-source-map'//不仅管自己的业务代码出错,也管第三方模块和loader的一些报错
    //devtool:'eval'//执行效率最快,性能最好,但是针对比较复杂的代码的情况下,提示内容不全面
	//devtool: 'cheap-module-eval-source-map',//在开发环境推荐使用,提示比较全,打包速度比较快
    //devtool: 'cheap-module-source-map',//在生产环境中推荐使用,提示效果会好一些
	
	
	entry: {
		main: './src/index.js'
	},
	module: {
		rules: [{
			test: /\.(jpg|png|gif)$/,
			use: {
				loader: 'url-loader',
				options: {
					name: '[name]_[hash].[ext]',
					outputPath: 'images/',
					limit: 10240
				}
			} 
		}, {
			test: /\.(eot|ttf|svg)$/,
			use: {
				loader: 'file-loader'
			} 
		}, {
			test: /\.scss$/,
			use: [
				'style-loader', 
				{
					loader: 'css-loader',
					options: {
						importLoaders: 2
					}
				},
				'postcss-loader',
				'sass-loader',
				
			]
		}]
	},
	plugins: [new HtmlWebpackPlugin({
		template: 'src/index.html'
	}), new CleanWebpackPlugin(['dist'])],
	output: {
		filename: '[name].js',
		path: path.resolve(__dirname, 'dist')
	}
}

Подробности смотрите на официальном сайте:devtool


Повысьте эффективность разработки с помощью WebPackDevServer

Устраните необходимость перезапускать npm run dev вручную каждый раз, когда вы пишете код в src.

1. Настроить в package.json

{
  "name": "haiyang",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "bundle": "webpack",
    "watch": "webpack --watch",// 加--watch自动监听代码的变化
    
  },
  
}

2. В webpack.config.js добавьте devServer

Установитьnpm i webpack-dev-server –D

  • contentBase : настроить корневой каталог файла среды выполнения службы разработки.
  • open : автоматически открыть браузер
  • хост: адрес хоста, где сервер разработки прослушивает
  • сжатие : разрешает ли сервер разработки сжатие, такое как gzip.
  • порт: порт, который прослушивает сервер разработки
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
	mode: 'development',
	devtool: 'cheap-module-eval-source-map',
	entry: {
		main: './src/index.js'
	},
+	devServer: {
		contentBase: './dist',
		open: true,
		port: 8080,
    	proxy: {//配置跨域,访问的域名会被代理到本地的3000端口
      		'/api': 'http://localhost:3000'
    	}
	},
	module: {
		rules: []
	},
	plugins: [],
	output: {
		filename: '[name].js',
		path: path.resolve(__dirname, 'dist')
	}
}

В package.json:

{
  "name": "haiyang",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "bundle": "webpack",
    "watch": "webpack --watch",// 加--watch自动监听代码的变化
    "start": "webpack-dev-server",//配置热更新
	
  },
 
}

Подробности смотрите на официальном сайте:dev-server

Расширение знаний: самостоятельно напишите инструмент, похожий на webpackdevserver

Просто поймите, функция неполная, вы можете расширить ее самостоятельно.

В package.json:

{
  "name": "haiyang",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "bundle": "webpack",
    "watch": "webpack --watch",// 加--watch自动监听代码的变化
    "start": "webpack-dev-server",//配置热更新
+	"server" : "node server.js" //自己写一个类似webpackdevserver的工具
  },
 
}

Установить :npm i express webpack-dev-middleware -D

Создайте файл server.js в корневом каталоге проекта.

в server.js

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const config = require('./webpack.config.js');
const complier = webpack(config);

const app = express();

app.use(webpackDevMiddleware(complier, {}));

app.listen(3000, () => {
	console.log('server is running');
});

горячая замена модуля

В package.json:

{
  "name": "haiyang",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server" //将文件打包到内存中,有助于开发
  },
}

в webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');

module.exports = {
	mode: 'development',
	devtool: 'cheap-module-eval-source-map',
	entry: {
		main: './src/index.js'
	},
	devServer: {
		contentBase: './dist',
		open: true,
		port: 8080,
+		hot: true,//开启热更新
+		hotOnly: true//尽管html功能没有实现,也不让浏览器刷新
	},
	module: {
		rules: [{
			test: /\.(jpg|png|gif)$/,
			use: {
				loader: 'url-loader',
				options: {
					name: '[name]_[hash].[ext]',
					outputPath: 'images/',
					limit: 10240
				}
			} 
		}, {
			test: /\.(eot|ttf|svg)$/,
			use: {
				loader: 'file-loader'
			} 
		}, {
			test: /\.scss$/,
			use: [
				'style-loader', 
				{
					loader: 'css-loader',
					options: {
						importLoaders: 2
					}
				},
				'postcss-loader',
				'sass-loader',
				
			]
		}, {
			test: /\.css$/,
			use: [
				'style-loader',
				'css-loader',
				'postcss-loader'
			]
		}]
	},
	plugins: [
		new HtmlWebpackPlugin({
			template: 'src/index.html'
		}), 
		new CleanWebpackPlugin(['dist']),
+		new webpack.HotModuleReplacementPlugin() //使用模块热更新插件
	],
	output: {
		filename: '[name].js',
		path: path.resolve(__dirname, 'dist')
	}
}

index.js

//如果模块启用了HMR,就可以用 module.hot.accept(),监听模块的更新。
if (module.hot) {
  module.hot.accept('./library.js', function() {
    // 使用更新过的 library 模块执行某些操作...
  })
}

будь осторожен:

При введении CSS, при использовании Frameworks Vue и реагируйте, вам не нужно писать модуль. Hot.Accept (), потому что при использовании CSS-погрузчика, Vue-Loader и Babel-Preset, HMR уже настроен, и вы делаете Не нужно писать это сами.

Подробности смотрите в официальной документации:hot-module-replacement api/hot-module-replacement concepts/hot-module-replacement


Используйте Babel для обработки синтаксиса ES6/7, экранированного в ES5.

Официальный сайт БАБЕЛ:babeljs.io/setup

Установите зависимости:

npm i babel-loader @babel/core @babel/preset-env -D
//生产依赖,兼容低版本浏览器
npm install --save @babel/polyfill

в webpack.config.js

module: {
  rules: [
    {
        test: /\.js$/,
     	exclude: /node_modules/,//不需要对第三方模块进行转换,耗费性能
     	loader: "babel-loader" ,
        options:{
            "presets": [["@babel/preset-env",{
                targets: {//这个项目运行在大于什么版本的浏览器上,已经支持es6的语法的高版本浏览器就不需要转义成es5了
                    edge: "17",
                    firefox: "60",
                    chrome: "67",
                    safari: "11.1",
                  },
                useBuiltIns:'usage' //按需添加polyfill,把用到的代码都转成低版本浏览器兼容的
            }]]
        }
    }
  ]
}

В index.js:

//在业务代码运行之前最顶部导入
import "@babel/polyfill";

Примечание. При разработке библиотек нельзя использовать сторонние модули или библиотеки компонентов @babel/polyfill этой программы, потому что объявление переменных станет глобальными переменными, загрязнит глобальную среду.

Установить:

npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
npm install --save @babel/runtime-corejs2

в webpack.config.js

module: {
  rules: [
    {
        test: /\.js$/,
     	exclude: /node_modules/,//不需要对第三方模块进行转换,耗费性能
     	loader: "babel-loader" ,
        options:{
            "plugins": [["@babel/plugin-transform-runtime",{
                "corejs": 2,
                "helpers": true,
                "regenerator": true,
                "useESModules": false
            }]]
        }
    }
  ]
}

Так как Babel нужно настроить много контента, нам нужно создать.babelrcдокумент.

Нет необходимости писать конфигурацию babel в webpack.config.js.

существует.babelrcсередина:

{
            "plugins": [["@babel/plugin-transform-runtime",{
                "corejs": 2,
                "helpers": true,
                "regenerator": true,
                "useESModules": false
            }]]
        }

Настроить упаковку кода React

Бизнес-код:

существует.babelrcсередина:

	{ 
            "presets": [
                ["@babel/preset-env",{
                targets: {
                    edge: "17",
                    firefox: "60",
                    chrome: "67",
                    safari: "11.1",
                  },
                useBuiltIns:'usage' 
            		}
                ],
                "@babel/preset-react"
            ]
        }
//执行顺序:从下往上,从右向左的顺序

Установить:

npm i react react-dom --save
npm install --save-dev @babel/preset-react

Подробности смотрите на официальном сайте:babel-loader


Три: WebPack Advanced

Tree Shaking: поддерживает только модуль ES, например.importа такжеexportВведение статических структурных свойств. При импорте модуля не импортируйте весь код, только необходимый код

В webpack.config.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');

module.exports = {
	mode: 'development',
	devtool: 'cheap-module-eval-source-map',
	entry: {
		main: './src/index.js'
	},
	devServer: {
		contentBase: './dist',
		open: true,
		port: 8080,
		hot: true,
		hotOnly: true
	},
	module: {
		rules: []
	},
	plugins: [],
+	optimization: { //在开发环境中加,生产环境不加
		usedExports: true
	},
	output: {
		filename: '[name].js',
		path: path.resolve(__dirname, 'dist')
	}
}

В package.json:

{
+ "sideEffects": ["*.css"], //对 所有的css文件 不使用Tree shaking。如果填 false,就是都需要用到Tree shaking
}

Подробности смотрите на официальном сайте:tree-shaking


Различная упаковка между режимами разработки и производства

Создайте два файла в корневом каталоге проекта, webpack.dev.js, webpack.prod.js.

webpack.dev.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');

module.exports = {
	mode: 'development',
	devtool: 'cheap-module-eval-source-map',
	entry: {
		main: './src/index.js'
	},
	devServer: {
		contentBase: './dist',
		open: true,
		port: 8080,
		hot: true,
		hotOnly: true
	},
	module: {
		rules: [{ 
			test: /\.js$/, 
			exclude: /node_modules/, 
			loader: 'babel-loader',
		}, {
			test: /\.(jpg|png|gif)$/,
			use: {
				loader: 'url-loader',
				options: {
					name: '[name]_[hash].[ext]',
					outputPath: 'images/',
					limit: 10240
				}
			} 
		}, {
			test: /\.(eot|ttf|svg)$/,
			use: {
				loader: 'file-loader'
			} 
		}, {
			test: /\.scss$/,
			use: [
				'style-loader', 
				{
					loader: 'css-loader',
					options: {
						importLoaders: 2
					}
				},
				'postcss-loader',
				'sass-loader',
				
			]
		}, {
			test: /\.css$/,
			use: [
				'style-loader',
				'css-loader',
				'postcss-loader'
			]
		}]
	},
	plugins: [
		new HtmlWebpackPlugin({
			template: 'src/index.html'
		}), 
		new CleanWebpackPlugin(['dist']),
		new webpack.HotModuleReplacementPlugin()
	],
	optimization: {
		usedExports: true
	},
	output: {
		filename: '[name].js',
		path: path.resolve(__dirname, 'dist')
	}
}

webpack.prod.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');

module.exports = {
	mode: 'production',
	devtool: 'cheap-module-source-map',
	entry: {
		main: './src/index.js'
	},
	
	module: {
		rules: [{ 
			test: /\.js$/, 
			exclude: /node_modules/, 
			loader: 'babel-loader',
		}, {
			test: /\.(jpg|png|gif)$/,
			use: {
				loader: 'url-loader',
				options: {
					name: '[name]_[hash].[ext]',
					outputPath: 'images/',
					limit: 10240
				}
			} 
		}, {
			test: /\.(eot|ttf|svg)$/,
			use: {
				loader: 'file-loader'
			} 
		}, {
			test: /\.scss$/,
			use: [
				'style-loader', 
				{
					loader: 'css-loader',
					options: {
						importLoaders: 2
					}
				},
				'postcss-loader',
				'sass-loader',
				
			]
		}, {
			test: /\.css$/,
			use: [
				'style-loader',
				'css-loader',
				'postcss-loader'
			]
		}]
	},
	plugins: [
		new HtmlWebpackPlugin({
			template: 'src/index.html'
		}), 
		new CleanWebpackPlugin(['dist']),
		
	],
	
	output: {
		filename: '[name].js',
		path: path.resolve(__dirname, 'dist')
	}
}

В package.json:

{
  "scripts": {
    "dev": "webpack-dev-server --config webpack.dev.js",
    "build": "webpack --config webpack.prod.js"
  },
}

Чтобы решить проблему webpack.dev.js, webpack.prod.js имеет много повторяющегося кода, создайте файл webpack.common.js в корневом каталоге проекта и извлеките общий код.

Установить :

npm i webpack-merge -D 

webpack.common.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');

module.exports = {

	entry: {
		main: './src/index.js'
	},
	
	module: {
		rules: [{ 
			test: /\.js$/, 
			exclude: /node_modules/, 
			loader: 'babel-loader',
		}, {
			test: /\.(jpg|png|gif)$/,
			use: {
				loader: 'url-loader',
				options: {
					name: '[name]_[hash].[ext]',
					outputPath: 'images/',
					limit: 10240
				}
			} 
		}, {
			test: /\.(eot|ttf|svg)$/,
			use: {
				loader: 'file-loader'
			} 
		}, {
			test: /\.scss$/,
			use: [
				'style-loader', 
				{
					loader: 'css-loader',
					options: {
						importLoaders: 2
					}
				},
				'postcss-loader',
				'sass-loader',
				
			]
		}, {
			test: /\.css$/,
			use: [
				'style-loader',
				'css-loader',
				'postcss-loader'
			]
		}]
	},
	plugins: [
		new HtmlWebpackPlugin({
			template: 'src/index.html'
		}), 
        new CleanWebpackPlugin(['dist'],{
            root:path.resolve(__dirname,'../')
        }),
		
	],
	
	output: {
		filename: '[name].js',
		path: path.resolve(__dirname, '../dist')
	}
}

webpack.dev.js

const webpack = require('webpack');
const merge = require('webpack-merge')
const commenConfig = require('./webpack.commin.js')

const devConfig = {
	mode: 'development',
	devtool: 'cheap-module-eval-source-map',
	
	devServer: {
		contentBase: './dist',
		open: true,
		port: 8080,
		hot: true,
		hotOnly: true
	},
	
	plugins: [	
		new webpack.HotModuleReplacementPlugin()
	],
	optimization: {
		usedExports: true
	},	
}
//将开发配置和公共配置做结合
module.exports = merge(commenConfig, devConfig)

webpack.prod.js

const merge = require('webpack-merge')
const commenConfig = require('./webpack.commin.js')

const prodConfig = {
	mode: 'production',
	devtool: 'cheap-module-source-map',
}
//将线上配置和公共配置做结合
module.exports = merge(commenConfig, prodConfig)

Наконец, создайте папку сборки в корневом каталоге, поместите webpack.common.js, webpack.dev.js, webpack.prod.js в папку сборки для унифицированного управления.

В package.json:

{
  "scripts": {
    "dev": "webpack-dev-server --config ./build/webpack.dev.js",
    "build": "webpack --config ./build/webpack.prod.js"
  },
}

Подробности смотрите в официальном документе на сайте:guides/production


Webpack и разделение кода

Установить:npm i lodash --save npm i babel-plugin-dynamic-import-webpack -D

Разделение кода независимо от веб-пакета для повышения производительности. Есть два способа реализовать разделение кода в webpack:

Первый способ: синхронный код: нужно только настроить оптимизацию в webpack.common.js

Второй метод: асинхронный код (импорт): асинхронный код без какой-либо настройки автоматически разделит код и поместит его в новый файл.

Первый способ: в webpack.common.js


module.exports = {
	entry: {
		main: './src/index.js'
	},
	
	module: {
		rules: []
	},
	plugins: [],
+    optimization:{
+       splitChunks:{ //启动代码分割,有默认配置项
+            chunks:'all'
+        }  
+    },
	
	output: {}
}

Второй метод.babelrcсередина:

{
	presets: [
		[
			"@babel/preset-env", {
				targets: {
					chrome: "67",
				},
				useBuiltIns: 'usage'
			}
		],
		"@babel/preset-react"
	],
+	plugins: ["dynamic-import-webpack"]
}

Подробности смотрите на официальном сайте:code-splitting


Подробное объяснение параметров конфигурации SplitChunksPlugin

Установить:npm install --save-dev @babeL/plugin-syntax-dynamic-import

В бизнесе index.js:


 function getComponent() {
 	return import(/* webpackChunkName:"lodash" */ 'lodash').then(({ default: _ }) => {
 		var element = document.createElement('div');
		element.innerHTML = _.join(['1', '2'], '-');
 		return element;
	})
}

 getComponent().then(element => {
 	document.body.appendChild(element);
 });

существует.babelrcсередина:

{
	presets: [
		[
			"@babel/preset-env", {
				targets: {
					chrome: "67",
				},
				useBuiltIns: 'usage'
			}
		],
		"@babel/preset-react"
	],
+	plugins: ["@babeL/plugin-syntax-dynamic-import"]
}

В webpack.common.js:


module.exports = {
	entry: {
		main: './src/index.js'
	},
	
	module: {
		rules: []
	},
	plugins: [],
+    optimization:{
+       splitChunks:{ //启动代码分割,不写有默认配置项
+            chunks: 'all',//参数all/initial/async,只对所有/同步/异步进行代码分割
              minSize: 30000, //大于30kb才会对代码分割
              maxSize: 0,
              minChunks: 1,//打包生成的文件,当一个模块至少用多少次时才会进行代码分割
              maxAsyncRequests: 5,//同时加载的模块数最多是5个
              maxInitialRequests: 3,//入口文件最多3个模块会做代码分割,否则不会
              automaticNameDelimiter: '~',//文件自动生成的连接符
              name: true,
            cacheGroups:{//对同步代码走缓存组
             vendors: {
                  test: /[\\/]node_modules[\\/]/,
                  priority: -10,//谁优先级大就把打包后的文件放到哪个组
    			filename:'vendors.js'
                },
            default: {
              minChunks: 2,
              priority: -20,
              reuseExistingChunk: true,//模块已经被打包过了,就不用再打包了,复用之前的就可以
              filename:'common.js' //打包之后的文件名   
            }
        }
+        }  
+    },
	
	output: {}
}

Подробности смотрите в официальной документации:split-chunks-plugin


Ленивая загрузка Ленивая загрузка, что такое фрагмент?

Пользователю нужно только загрузить код, соответствующий той функции, которую пользователю необходимо использовать в данный момент, то есть так называемая загрузка по требованию.При оптимизации загрузки по требованию для одностраничных приложений обычно соблюдаются следующие принципы. усыновленный:

  • Разделите функции сайта, по одному фрагменту для каждой категории
  • Непосредственно загружайте функции, необходимые для открытия страницы в первый раз, и показывайте ее пользователю как можно скорее.
  • Некоторые функции, которые зависят от большого количества кода, могут быть загружены по запросу.
  • Код разделения требует времени для загрузки по требованию

Каждый файл представляет собой кусок

Подробности смотрите в официальной документации:lazy-loading


Анализ упаковки, предварительная загрузка, предварительная выборка

Открытый URL: инструмент анализа веб-пакетов:https://github.com/webpack/analyse

в пакете.json

{  
  "scripts": {
    "dev-build": "webpack --profile --json > stats.json --config ./build/webpack.dev.js", //把打包过程的描述放在stats.json文件中
    "dev": "webpack-dev-server --config ./build/webpack.dev.js",
    "build": "webpack --config ./build/webpack.prod.js"
  },
}

запустить в консолиnpm run dev-buildи создайте файл stats.json в корневом каталоге. открытый URLhttp://webpack.github.io/analyse/, Загрузите файл stats.json, и появятся результаты анализа.

Подробности смотрите в официальной документации:инструмент для анализа пакетов bundle-analysis

представлятьwebpack-bundle-analyzerиспользование:

используяwebpack-bundle-analyzerВы можете видеть размер каждого модуля проекта, который можно оптимизировать по мере необходимости.

Официальный сайт карты городской застройки:

Установить:

# NPM
npm install --save-dev webpack-bundle-analyzer
# Yarn
yarn add -D webpack-bundle-analyzer

Конфигурация: в webpack.config.js:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin(
    	{
              analyzerMode: 'server',
              analyzerHost: '127.0.0.1',
              analyzerPort: 8889,
              reportFilename: 'report.html',
              defaultSizes: 'parsed',
              openAnalyzer: true,
              generateStatsFile: false,
              statsFilename: 'stats.json',
              statsOptions: null,
              logLevel: 'info'
            }
    )
  ]
}

Вывод: в package.json:

"analyz": "NODE_ENV=production npm_config_report=true npm run build"

Онлайн анализ: Введите в консоли:

webpack --profile --json > stats.json
  • профиль: запись трудоемкой информации в процессе строительства;
  • json: вывод результатов сборки в формате JSON и, наконец, вывод только файла .json, который включает всю информацию, связанную со сборкой.
  • Webpack официально предоставляет инструмент визуального анализаWebpack Analyse
  • Модули: показать все модули, каждый модуль соответствует файлу. И он также включает график зависимости между всеми модулями, путь к модулю, идентификатор модуля, чанк, к которому принадлежит модуль, и размер модуля;
  • Фрагменты: показать все блоки кода, блок кода содержит несколько модулей. А также содержит идентификатор, имя, размер блока кода, количество модулей, которые содержит каждый блок кода, и график зависимости между блоками кода;
  • Активы: отображение всех ресурсов выходных файлов, включая .js, .css, изображения и т. д. А также имя файла, размер, из какого блока кода взялся файл;
  • Предупреждения: отображает все предупреждения в процессе сборки;
  • Ошибки: отображает все сообщения об ошибках, возникших в процессе сборки;
  • Подсказки: покажите время, затраченное на обработку каждого модуля.

Откройте консоль Google, чтобы просмотреть использование кода, нажмитеctrl+shift+p, введите покрытие для просмотра.

модуль предварительной выборки/предварительной загрузки

Предположим, есть компонент HomePage, внутри которого находится компонент входа в систему LoginButton.js, а затем загружает компонент LoginModel по требованию после нажатия.

LoginButton.js:

import(/* webpackPrefetch: true */ 'LoginModal');

это создаст<link rel="prefetch" href="login-modal-chunk.js">и добавляется к заголовку страницы, указывая браузеру выполнять предварительную выборку во время простоя.login-modal-chunk.jsдокумент. То есть, пока загружается домашняя страница, модуль входа в систему также будет загружаться во время простоя.

Суммировать:

/* webpackPrefetch: true */: После того, как основной процесс загрузки загружен, другие загружаются в режиме ожидания, и когда вы нажимаете другой, вам нужно только читать из кеша, и производительность выше. Рекомендуется использовать для улучшения использования кода. Напишите некоторый код, который можно использовать только после взаимодействия с асинхронными компонентами, и загрузите логику этого фрагмента кода в виде отложенной загрузки, что повышает производительность и ускоряет доступ к странице.

/* webpackPreload: true */: Загружать параллельно основному процессу загрузки.

Подробности смотрите в официальной документации:prefetchingpreloading-modules


Разделение кода файлов CSS

в webpack.config.js

module.exports = {
	entry: {
		main: './src/index.js'
	},
    module: {
       
    },
    plugins: [],
	optimization: {
		splitChunks: {
      	 chunks: 'all'
    }
	},
	output: {
		filename: '[name].js',//入口文件打包后生成的文件名
+         chunkFilename: '[name].chunk.js',//main.js异步加载的间接的js文件。用来打包import('module')方法中引入的模块
		path: path.resolve(__dirname, '../dist')
	}
}

Поскольку загрузка CSS и JS может выполняться параллельно, когда файл HTML очень большой, мы можем извлечь CSS отдельно и загрузить его.

  • mini-css-extract-plugin: Общая среда онлайн, чтобы использовать этот плагин, потому что они не поддерживают HMR в среде разработки.
  • Имя файла записи пакета
  • chunkFilename используется для упаковкиimport('module')Модули, импортированные в методы

Установить :

//抽离css文件
npm install --save-dev mini-css-extract-plugin
//压缩css文件
npm i optimize-css-assets-webpack-plugin -D

В webpack.prod.js:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const merge = require('webpack-merge');
const commonConfig = require('./webpack.common.js');


const prodConfig = {
	mode: 'production',
	devtool: 'cheap-module-source-map',
	module: {
		rules:[{
			test: /\.scss$/,
			use: [
+				MiniCssExtractPlugin.loader, 
				{
					loader: 'css-loader',
					options: {
						importLoaders: 2
					}
				},
				'postcss-loader',
				'sass-loader',
				
			]
		}, {
			test: /\.css$/,
			use: [
+				MiniCssExtractPlugin.loader,
				'css-loader',
				'postcss-loader'
			]
		}]
	},
+	optimization: {
		minimizer: [new OptimizeCSSAssetsPlugin({})]
	},
	plugins: [
+		new MiniCssExtractPlugin({
			filename: '[name].css',//直接引用的css文件
			chunkFilename: '[name].chunk.css'//间接引用的css文件
		})
	]
}

module.exports = merge(commonConfig, prodConfig);

в webpack.dev.js

const webpack = require('webpack');
const merge = require('webpack-merge');
const commonConfig = require('./webpack.common.js');

const devConfig = {
	mode: 'development',
	devtool: 'cheap-module-eval-source-map',
	devServer: {
		contentBase: './dist',
		open: true,
		port: 8080,
		hot: true
	},
	module: {
		rules: [{
			test: /\.scss$/,
			use: [
				'style-loader', 
				{
					loader: 'css-loader',
					options: {
						importLoaders: 2
					}
				},
				'postcss-loader',
				'sass-loader',
				
			]
		}, {
			test: /\.css$/,
			use: [
				'style-loader',
				'css-loader',
				'postcss-loader'
			]
		}]
	},
	plugins: [
		new webpack.HotModuleReplacementPlugin()
	],
}

module.exports = merge(commonConfig, devConfig);

В webpack.common.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
	entry: {
		main: './src/index.js',
	},
	module: {
		rules: [{ 
			test: /\.js$/, 
			exclude: /node_modules/, 
			loader: 'babel-loader',
		}, {
			test: /\.(jpg|png|gif)$/,
			use: {
				loader: 'url-loader',
				options: {
					name: '[name]_[hash].[ext]',
					outputPath: 'images/',
					limit: 10240
				}
			} 
		}, {
			test: /\.(eot|ttf|svg)$/,
			use: {
				loader: 'file-loader'
			} 
		}]
	},
	plugins: [
		new HtmlWebpackPlugin({
			template: 'src/index.html'
		}), 
		new CleanWebpackPlugin(['dist'], {
			root: path.resolve(__dirname, '../')
		})
	],
	optimization: {
		usedExports: true,//TreeShaking
		splitChunks: {
      chunks: 'all'
    }
	},
	output: {
		filename: '[name].js',
		chunkFilename: '[name].chunk.js',
		path: path.resolve(__dirname, '../dist')
	}
}

В package.json:

{
    "sideEffects": ["*.css"] //除了css文件,其余的都TreeShaking
}

Подробности смотрите в официальной документации:mini-css-extract-plugin


Webpack и кэширование браузера (Кэширование)

В webpack.common.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
	entry: {
		main: './src/index.js',
	},
	module: {
		rules: [{ 
			test: /\.js$/, 
			exclude: /node_modules/, 
			loader: 'babel-loader',
		}, {
			test: /\.(jpg|png|gif)$/,
			use: {
				loader: 'url-loader',
				options: {
					name: '[name]_[hash].[ext]',
					outputPath: 'images/',
					limit: 10240
				}
			} 
		}, {
			test: /\.(eot|ttf|svg)$/,
			use: {
				loader: 'file-loader'
			} 
		}]
	},
	plugins: [
		new HtmlWebpackPlugin({
			template: 'src/index.html'
		}), 
		new CleanWebpackPlugin(['dist'], {
			root: path.resolve(__dirname, '../')
		})
	],
	optimization: {
+		runtimeChunk: {//兼容老版本webpack4,把manifest打包到runtime里,不影响业务代码和第三方模块
			name: 'runtime'
		},
		usedExports: true,
		splitChunks: {
      chunks: 'all',
      cacheGroups: {
      	vendors: {
      		test: /[\\/]node_modules[\\/]/,
      		priority: -10,
      		name: 'vendors',
      	}
      }
    }
	},
	performance: false,//禁止提示性能上的一些问题
+	output: {
		path: path.resolve(__dirname, '../dist')
	}
}

В webpack.dev.js:

const webpack = require('webpack');
const merge = require('webpack-merge');
const commonConfig = require('./webpack.common.js');

const devConfig = {
	mode: 'development',
	devtool: 'cheap-module-eval-source-map',
	devServer: {
		contentBase: './dist',
		open: true,
		port: 8080,
		hot: true
	},
	module: {
		rules: [{
			test: /\.scss$/,
			use: [
				'style-loader', 
				{
					loader: 'css-loader',
					options: {
						importLoaders: 2
					}
				},
				'postcss-loader',
				'sass-loader',
				
			]
		}, {
			test: /\.css$/,
			use: [
				'style-loader',
				'css-loader',
				'postcss-loader'
			]
		}]
	},
	plugins: [
		new webpack.HotModuleReplacementPlugin()
	],
+	output: {
		filename: '[name].js',
		chunkFilename: '[name].js',
	}
}

module.exports = merge(commonConfig, devConfig);

В webpack.prod.js:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const merge = require('webpack-merge');
const commonConfig = require('./webpack.common.js');

const prodConfig = {
	mode: 'production',
	devtool: 'cheap-module-source-map',
	module: {
		rules:[{
			test: /\.scss$/,
			use: [
				MiniCssExtractPlugin.loader, 
				{
					loader: 'css-loader',
					options: {
						importLoaders: 2
					}
				},
				'postcss-loader'
				'sass-loader',
				
			]
		}, {
			test: /\.css$/,
			use: [
				MiniCssExtractPlugin.loader,
				'css-loader',
				'postcss-loader'
			]
		}]
	},
	optimization: {
		minimizer: [new OptimizeCSSAssetsPlugin({})]
	},
	plugins: [
		new MiniCssExtractPlugin({
			filename: '[name].css',
			chunkFilename: '[name].chunk.css'
		})
	],
+	output: {
		filename: '[name].[contenthash].js', //源代码不变,hash值就不会变,解决浏览器缓存问题。打包上线时,用户只需要更新有变化的代码,没有变化的从浏览器缓存读取
		chunkFilename: '[name].[contenthash].js'
	}
}

module.exports = merge(commonConfig, prodConfig);

Подробности смотрите в официальном документе на сайте:manifest


Шиминг (Шимминг)

В webpack.common.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');

module.exports = {
	entry: {
		main: './src/index.js',
	},
	module: {
		rules: [{ 
			test: /\.js$/, 
			exclude: /node_modules/,
			use: [{
				loader: 'babel-loader'
			}, {
				loader: 'imports-loader?this=>window'
			}]
		}, {
			test: /\.(jpg|png|gif)$/,
			use: {
				loader: 'url-loader',
				options: {
					name: '[name]_[hash].[ext]',
					outputPath: 'images/',
					limit: 10240
				}
			} 
		}, {
			test: /\.(eot|ttf|svg)$/,
			use: {
				loader: 'file-loader'
			} 
		}]
	},
	plugins: [
		new HtmlWebpackPlugin({
			template: 'src/index.html'
		}), 
		new CleanWebpackPlugin(['dist'], {
			root: path.resolve(__dirname, '../')
		}),
+		new webpack.ProvidePlugin({
			$: 'jquery',//发现模块中有$字符串,就自动引入iquery,就可以用jquery
			_join: ['lodash', 'join']//_join代表lodash里的join方法
		}),
	],
	optimization: {
		runtimeChunk: {
			name: 'runtime'
		},
		usedExports: true,
		splitChunks: {
      chunks: 'all',
      cacheGroups: {
      	vendors: {
      		test: /[\\/]node_modules[\\/]/,
      		priority: -10,
      		name: 'vendors',
      	}
      }
    }
	},
	performance: false,
	output: {
		path: path.resolve(__dirname, '../dist')
	}
}

如果想让每个js模块的this都指向window:

Установить:npm install imports-loader -D

В webpack.common.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');

module.exports = {
	entry: {
		main: './src/index.js',
	},
	module: {
		rules: [{ 
			test: /\.js$/, 
			exclude: /node_modules/,
			use: [{
				loader: 'babel-loader'
			}, {//每个js模块的this都指向window
+				loader: 'imports-loader?this=>window'
			}]
		}, {
			test: /\.(jpg|png|gif)$/,
			use: {
				loader: 'url-loader',
				options: {
					name: '[name]_[hash].[ext]',
					outputPath: 'images/',
					limit: 10240
				}
			} 
		}, {
			test: /\.(eot|ttf|svg)$/,
			use: {
				loader: 'file-loader'
			} 
		}]
	},
	plugins: [
		new HtmlWebpackPlugin({
			template: 'src/index.html'
		}), 
		new CleanWebpackPlugin(['dist'], {
			root: path.resolve(__dirname, '../')
		}),
+		new webpack.ProvidePlugin({
			$: 'jquery',//发现模块中有$字符串,就自动引入iquery,就可以用jquery
			_join: ['lodash', 'join']//_join代表lodash里的join方法
		}),
	],
	optimization: {
		runtimeChunk: {
			name: 'runtime'
		},
		usedExports: true,
		splitChunks: {
      chunks: 'all',
      cacheGroups: {
      	vendors: {
      		test: /[\\/]node_modules[\\/]/,
      		priority: -10,
      		name: 'vendors',
      	}
      }
    }
	},
	performance: false,
	output: {
		path: path.resolve(__dirname, '../dist')
	}
}

Подробности смотрите в официальной документации:imports-loader shimming


Использование переменных среды

Требуется только один файл common.js, чтобы отличить среду разработки от рабочей среды путем передачи разных параметров в package.json.

В package.json:

{
  "name": "haiyang",
  "sideEffects": [
    "*.css"
  ],
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev-build": "webpack --config ./build/webpack.common.js",
    "dev": "webpack-dev-server --config ./build/webpack.common.js",
    "build": "webpack --env.production --config ./build/webpack.common.js" //通过--env.production,把环境变量传进去
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.2.0",
    "@babel/plugin-syntax-dynamic-import": "^7.2.0",
    "@babel/plugin-transform-runtime": "^7.2.0",
    "@babel/preset-env": "^7.2.0",
    "@babel/preset-react": "^7.0.0",
    "autoprefixer": "^9.3.1",
    "babel-loader": "^8.0.4",
    "clean-webpack-plugin": "^1.0.0",
    "css-loader": "^1.0.1",
    "express": "^4.16.4",
    "file-loader": "^2.0.0",
    "html-webpack-plugin": "^3.2.0",
    "imports-loader": "^0.8.0",
    "mini-css-extract-plugin": "^0.5.0",
    "node-sass": "^4.10.0",
    "optimize-css-assets-webpack-plugin": "^5.0.1",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.1",
    "url-loader": "^1.1.2",
    "webpack-cli": "^3.1.2",
    "webpack-dev-middleware": "^3.4.0",
    "webpack-dev-server": "^3.1.10",
    "webpack-merge": "^4.1.5"
  },
  "dependencies": {
    "@babel/polyfill": "^7.0.0",
    "@babel/runtime": "^7.2.0",
    "@babel/runtime-corejs2": "^7.2.0",
    "jquery": "^3.3.1",
    "lodash": "^4.17.11",
    "react": "^16.6.3",
    "react-dom": "^16.6.3",
    "webpack": "^4.25.1"
  }
}

В webpack.common.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
const merge = require('webpack-merge');
const devConfig = require('./webpack.dev.js');
const prodConfig = require('./webpack.prod.js');
const commonConfig = {
	entry: {
		main: './src/index.js',
	},
	module: {
		rules: [{ 
			test: /\.js$/, 
			exclude: /node_modules/,
			use: [{
				loader: 'babel-loader'
			}, {
				loader: 'imports-loader?this=>window'
			}]
		}, {
			test: /\.(jpg|png|gif)$/,
			use: {
				loader: 'url-loader',
				options: {
					name: '[name]_[hash].[ext]',
					outputPath: 'images/',
					limit: 10240
				}
			} 
		}, {
			test: /\.(eot|ttf|svg)$/,
			use: {
				loader: 'file-loader'
			} 
		}]
	},
	plugins: [
		new HtmlWebpackPlugin({
			template: 'src/index.html'
		}), 
		new CleanWebpackPlugin(['dist'], {
			root: path.resolve(__dirname, '../')
		}),
		new webpack.ProvidePlugin({
			$: 'jquery',
			_join: ['lodash', 'join']
		}),
	],
	optimization: {
		runtimeChunk: {
			name: 'runtime'
		},
		usedExports: true,
		splitChunks: {
      chunks: 'all',
      cacheGroups: {
      	vendors: {
      		test: /[\\/]node_modules[\\/]/,
      		priority: -10,
      		name: 'vendors',
      	}
      }
    }
	},
	performance: false,
	output: {
		path: path.resolve(__dirname, '../dist')
	}
}

module.exports = (env) => {
	if(env && env.production) {//线上环境
		return merge(commonConfig, prodConfig);
	}else {//开发环境
		return merge(commonConfig, devConfig);
	}
}


В webpack.dev.js:

const webpack = require('webpack');

const devConfig = {
	mode: 'development',
	devtool: 'cheap-module-eval-source-map',
	devServer: {
		contentBase: './dist',
		open: true,
		port: 8080,
		hot: true
	},
	module: {
		rules: [{
			test: /\.scss$/,
			use: [
				'style-loader', 
				{
					loader: 'css-loader',
					options: {
						importLoaders: 2
					}
				},
				'postcss-loader',
				'sass-loader',
				
			]
		}, {
			test: /\.css$/,
			use: [
				'style-loader',
				'css-loader',
				'postcss-loader'
			]
		}]
	},
	plugins: [
		new webpack.HotModuleReplacementPlugin()
	],
	output: {
		filename: '[name].js',
		chunkFilename: '[name].js',
	}
}

module.exports = devConfig;

В webpack.prod.js:

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

const prodConfig = {
	mode: 'production',
	devtool: 'cheap-module-source-map',
	module: {
		rules:[{
			test: /\.scss$/,
			use: [
				MiniCssExtractPlugin.loader, 
				{
					loader: 'css-loader',
					options: {
						importLoaders: 2
					}
				},
				'postcss-loader',
				'sass-loader',
				
			]
		}, {
			test: /\.css$/,
			use: [
				MiniCssExtractPlugin.loader,
				'css-loader',
				'postcss-loader'
			]
		}]
	},
	optimization: {
		minimizer: [new OptimizeCSSAssetsPlugin({})]
	},
	plugins: [
		new MiniCssExtractPlugin({
			filename: '[name].css',
			chunkFilename: '[name].chunk.css'
		})
	],
	output: {
		filename: '[name].[contenthash].js',
		chunkFilename: '[name].[contenthash].js'
	}
}

module.exports = prodConfig;

Четвертый: случай фактической конфигурации Webpack

Упаковка библиотеки: код библиотеки упакован через webpack

Исходный код хранилища [41

В webpack.config.js:


const path = require('path');

module.exports = {
	mode: 'production',
	entry: './src/index.js',
	externals: 'lodash',
	output: {
		path: path.resolve(__dirname, 'dist'),
		filename: 'library.js',
		library: 'root', //支持通过<scritp src=ilibrary. js'></script> 标签引入,在全局变量增加一个root变量
		libraryTarget: 'umd' //别人用的时候,通过任何形式引入库都可以,比如AMD,CMD,ES MODULE,Commonjs
        
        // library: 'root',//打包生成全局变量root
		// libraryTarget: 'this' //把全局变量root挂载到this上,可以填umd,this,window,global
        
        // externals: {
        // 	lodash:{
        // 		root:'_', //是用script标签引入进来的,必须在全局注入一个 _ 变量,下面的library才能正常执行
        // 		commonjs:'lodash',//在用commonjs规范引入是,名字必须是lodash
        // 	}

        // }

	}
}

В package.json:

"main": "./dist/library.js", //最终要给别人使用的

существуетnpmЗарегистрируйте аккаунт на официальном сайте и введите в командной строке:

//添加用户名和密码
npm adduser 
//把项目发布到npm官网上
npm publish
//当别人用你发布的库时
npm i + 库名 

Подробности смотрите в официальной документации:externals author-libraries


Прогрессивное веб-приложение: настройте pwa в веб-пакете

Прогрессивные веб-приложения, PWA можно использовать для многих целей. Наиболее важным из них является то, что приложение может продолжать функционировать в **автономном режиме**. Это делается с помощью файла с именемService Workersвеб-технологии для достижения. pwa используется только в онлайн-среде, не требуется для разработки

Исходный код хранилища [42

Установить:

//模拟服务器
npm i http-server -D
//添加 workbox-webpack-plugin 插件,然后调整 webpack.config.js 文件
npm install workbox-webpack-plugin --save-dev

В package.json:

"scripts": {
 +   "start": "http-server dist",//在dist目录下运行http-server服务
    "dev": "webpack-dev-server --config ./build/webpack.dev.js",
    "build": "webpack --config ./build/webpack.prod.js"
  },

pwa используется только в онлайн-среде, не требуется для разработки, просто нужно изменить webpack.prod.js,

В webpack.prod.js:

const WorkboxPlugin = require('workbox-webpack-plugin');
plugins: [
		new MiniCssExtractPlugin({
			filename: '[name].css',
			chunkFilename: '[name].chunk.css'
		}),
+		new WorkboxPlugin.GenerateSW({
			clientsClaim: true,
			skipWaiting: true
		})
	],

Использование pwa в бизнес-коде index.js

console.log('hello, haiyang');

if ('serviceWorker' in navigator) { //如果浏览器支持serviceWorker,就执行以下代码
	window.addEventListener('load', () => {
		navigator.serviceWorker.register('/service-worker.js')
			.then(registration => {//注册成功
				console.log('service-worker registed');
			}).catch(error => {//没注册成功
				console.log('service-worker register error');
			})
	})
}

Подробности смотрите в официальной документации:progressive-web-application


Настройка упаковочной машины

TypeScriptЭто надмножество JavaScript с добавленной системой типов, которое можно скомпилировать в обычный код JavaScript. В этом руководстве мы узнаем, как интегрировать webpack с TypeScript.

Исходный код хранилища [43

Установить:

npm install --save-dev typescript ts-loader

В webpack.config.js:

const path = require('path');

module.exports = {
	mode: 'production',
	entry: './src/index.tsx',
	module: {
		rules: [{
			test: /\.tsx?$/,
			use: 'ts-loader',
			exclude: /node_modules/
		}]
	},
	output: {
		filename: 'bundle.js',
		path: path.resolve(__dirname, 'dist')
	}
}

Создайте файл tsconfig.json в корневом каталоге проекта:

{
	"compilerOpitons": {
		"outDir": "./dist",
		"module": "es6",//模块引入的方式
		"target": "es5",//转换为es5,在大部分浏览器都能运行
		"allowJs": true, //在typescript中允许引入js文件
	}
}

При установке сторонней библиотеки из npm не забудьте также установить определение типизации библиотеки. ты можешь начатьTypeSearchНайдите и установите файлы объявления типов для этих сторонних библиотек. При его использовании может быть предупреждение, если есть какая-либо ошибка, чтобы ее было легко исправить.

Установить:

//在typescript里用loadah
npm install --save-dev @types/lodash

Подробности смотрите в официальной документации:typescript


Переадресация запроса с помощью WebpackDevServer

Исходный код хранилища [44

Установить:

//向服务器发送axios请求
npm i axios -D

В index.js:

componentDidMount() {
		axios.get('/react/api/header.json')
			.then((res) => {
				console.log(res);
			})
	}

В webpack.config.js:

devServer: {
		contentBase: './dist',
		open: true,
		port: 8080,
		hot: true,
		hotOnly: true,
+		proxy: {//开发时方便接口转发,线上不用
			'/react/api': {//访问 /react/api 时,代理到 target 上
				target: 'https://www.dell-lee.com',
				secure: false,//对https协议的网址的请求的转发
     //   拦截,请求的是html,不走代理直接返回  /index.html文件          
	//bypass: function(req, res, proxyOptions) {
      //    if (req.headers.accept.indexOf('html') !== -1) {
      //      console.log('Skipping proxy for browser request.');
       //     return '/index.html';
       //   }
     //   },
				pathRewrite: {
					'header.json': 'demo.json' //最后拿的是demo.json的数据
				},
				changeOrigin: true,//解决网站对接口的限制
				headers: {//变更请求头
					host: 'www.dell-lee.com',
				}
			}
		}
	},

Подробности смотрите в официальной документации:devserverproxy


WebpackDevServer решает проблемы маршрутизации одностраничных приложений

Исходный код хранилища [45

Установить:

npm i react-router-dom --save

В webpack.config.js:

devServer: {//配置只在开发时有效,上线时后端也需配置
		contentBase: './dist',
		open: true,
		port: 8080,
		hot: true,
		hotOnly: true,
+		historyApiFallback: true,
    	//historyApiFallback: {
         // rewrites: [//访问任何路径都展示index.html页面
          //  { from: /\.*/, to: '/index.html' },
          //]
        //},
		proxy: {
			'/react/api': {
				target: 'https://www.dell-lee.com',
				secure: false,
				pathRewrite: {
					'header.json': 'demo.json'
				},
				changeOrigin: true,
				headers: {
					host: 'www.dell-lee.com',
				}
			}
		}
	},

Подробности смотрите в официальной документации:devserverhistoryapifallback


EsLint конфигурация Webpack

Исходный код хранилища [46

Установить:

//安装eslint工具,规范项目中的代码
npm i eslint -D
npm i babel-eslint -D
npm i eslint-loader -D
//快速生成eslint配置
npx eslint --init

В .eslintrc.js:

module.exports = {
	"extends": "airbnb",
  "parser": "babel-eslint",
  "rules": {
    "react/prefer-stateless-function": 0,
    "react/jsx-filename-extension": 0
  },
  globals: {
    document: false
  }
};

Подробности смотрите в официальной документации:eslint

Установите плагин eslint в редакторе vscode для автоматического обнаружения синтаксических ошибок. (Рекомендуемое использование)

В webpack.config.js:

devServer: {
+		overlay: true,//在浏览器弹出提示有错误
	},


rules: [{ 
			test: /\.js$/, 
			exclude: /node_modules/, 
	+		use: ['babel-loader', 'eslint-loader'] //先检查代码写的是否规范,然后在转换成es5
		},
        ...],

В реальном проекте также нельзя настраивать eslint в webpack, при отправке git-репозитория git перехватывает eslint src. Но графической интерактивной подсказки об ошибке нет.

Подробности смотрите в официальной документации:eslint-loader


Способы улучшить скорость упаковки webpack

Исходный код хранилища [47

1. Следите за технологическими итерациями (Node, Npm, Yarn)

2. Примените загрузчик к как можно меньшему количеству модулей

3. Плагин максимально прост и надежен

4. Разрешить разумную конфигурацию параметра

Исходный код хранилища [48

Введите файлы ресурсов для написания суффиксов, например файлы изображений (.jpg, .png, .svg), и настройте код логики в расширениях: extensions: ['.js', '.jsx']

5. Используйте DLLPlugin для повышения скорости упаковки

Подробности смотрите в официальной документации:dll-plugin

Исходный код хранилища [49

Реализуйте сторонние модули, которые будут упакованы только один раз

Установить:

npm i add-asset-html-webpack-plugin --save

Создайте файл webpack.dll.js в папке сборки: упакуйте сторонние модули отдельно, чтобы сгенерировать файл vendor.dll.js, все сторонние модули находятся в этом файле.

const path = require('path');
const webpack = require('webpack');

module.exports = {
	mode: 'production',
	entry: {
		vendors: ['lodash'],
		react: ['react', 'react-dom'],
		jquery: ['jquery']
	},
	output: {
		filename: '[name].dll.js',
		path: path.resolve(__dirname, '../dll'),
		library: '[name]'//打包生成的库名,通过全局变量的形式暴露到全局
	},
	plugins: [
		new webpack.DllPlugin({//对暴露到全局的代码进行分析,生成vendors.manifest.json 的映射文件,
			name: '[name]',
			path: path.resolve(__dirname, '../dll/[name].manifest.json'),
		})
	]
}

В webpack.common.js:

const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
const files = fs.readdirSync(path.resolve(__dirname, '../dll'));
files.forEach(file => {
	if(/.*\.dll.js/.test(file)) {
		plugins.push(new AddAssetHtmlWebpackPlugin({//将打包好的dll文件挂载到html中
			filepath: path.resolve(__dirname, '../dll', file)
		}))
	}
	if(/.*\.manifest.json/.test(file)) {
		plugins.push(new webpack.DllReferencePlugin({//分析第三方模块是否已经在dll文件里,如果里面有就不用再node_modules在分析打包了
			manifest: path.resolve(__dirname, '../dll', file)
		}))
	}
})

Добавьте скрипт в package.json:

"scripts": {
    "dev-build": "webpack --config ./build/webpack.dev.js",
    "dev": "webpack-dev-server --config ./build/webpack.dev.js",
    "build": "webpack --config ./build/webpack.prod.js",
 +   "build:dll": "webpack --config ./build/webpack.dll.js"
  }

Сначала выполнить в консолиnpm run build:dllСоздайте соответствующие файлы XXX.dll.js и XXX.manifest.json. Когда вы будете выполнять npm run build или npm run dev в будущем, вам не нужно искать соответствующий модуль в node_modules для анализа, вы можете напрямую использовать упакованный XXX.dll.js для сохранения скорости упаковки.

Суммировать:

Если подключаемый модуль DLLPlugin не используется, при введении стороннего модуля необходимо анализировать каждый пакет, на что расходуется производительность пакета. Используйте DLLPlugin для повышения скорости упаковки.При первой упаковке упакуйте сторонний модуль отдельно, чтобы создать файл vendor.dll.js, а затем напрямую импортируйте ранее упакованный сторонний модуль из vendors.dll.js, когда упаковка. , скорость будет быстрее.

Для этого вам нужно выполнить некоторые настройки:

Сначала настройте файл webpack.dll.js, добавьте скрипт в package.json и настройте файл webpack.common.js.

==============================================================

Файл с расширением .dll называется динамически подключаемой библиотекой, которая может содержать функции и данные, вызываемые другими модулями.

  • Разделите базовые модули на отдельные динамически подключаемые библиотеки.
  • Когда импортируемый модуль находится в динамической библиотеке, модуль не может быть снова упакован, но получен из динамической библиотеки.dll-plugin

определить DLL

  • Плагин DllPlugin: используется для упаковки библиотеки динамической компоновки.
  • DllReferencePlugin: добавьте библиотеку динамической компоновки, упакованную подключаемым модулем DllPlugin, в файл конфигурации.

В webpack.dll.js:

module.exports = {
    entry: {
        react: ['react'] //react模块打包到一个动态连接库
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].dll.js', //输出动态连接库的文件名称
        library: '_dll_[name]' //全局变量名称
    },
    plugins: [
        new webpack.DllPlugin({
            name: '_dll_[name]', //和output.library中一致,值就是输出的manifest.json中的 name值
            path: path.join(__dirname, 'dist', '[name].manifest.json')
        })
    ]
}
webpack --config webpack.dll.config.js --mode production

Использование файлов библиотеки динамической компоновки

В webpack.common.js:

plugins: [
+        new webpack.DllReferencePlugin({
+            manifest: require(path.join(__dirname, 'dist', 'react.manifest.json')),
+        })
    ],
webpack --config webpack.config.js --mode development

==============================================================

6. Размер файла управления пакетом

Настройте встряхивание дерева, чтобы удалить неиспользуемый код. Настройте плагин SplitChunks.

7. thread-loader, parallel-webpack, многопроцессорная упаковка happypack

HappyPack

HappyPack позволяет Webpack разбивать задачи на несколько подпроцессов для одновременного выполнения, а затем отправлять результаты в основной процесс после обработки подпроцессов.happypack

Установить:npm i happypack@next -D

Конфигурация:

module: {
        rules: [{
            test: /\.js$/,
            //把对.js文件的处理转交给id为babel的HappyPack实例
 +          use: 'happypack/loader?id=babel',
            include: path.resolve(__dirname, 'src'),
            exclude: /node_modules/
        }, {
            //把对.css文件的处理转交给id为css的HappyPack实例
            test: /\.css$/,
+           use: 'happypack/loader?id=css',
            include: path.resolve(__dirname, 'src')
        }],
        noParse: [/react\.min\.js/]
    },
plugins: [
        //用唯一的标识符id来代表当前的HappyPack是用来处理一类特定文件
        new HappyPack({
            id: 'babel',
            //如何处理.js文件,和rules里的配置相同
            loaders: [{
                loader: 'babel-loader',
                query: {
                    presets: [
                        "env", "react"
                    ]
                }
            }]
        }),
        new HappyPack({
            id: 'css',
            loaders: ['style-loader', 'css-loader'],
            threads: 4, //代表开启几个子进程去处理这一类型的文件
            verbose: true //是否允许输出日子
        })
    ],
ParallelUglifyPlugin

ParallelUglifyPluginВы можете превратить последовательное сжатие файлов JS в открытие нескольких подпроцессов для параллельного выполнения.

Установить:npm i -D webpack-parallel-uglify-plugin

Конфигурация:

new ParallelUglifyPlugin({
            workerCount: 3, //开启几个子进程去并发的执行压缩。默认是当前运行电脑的 CPU 核数减去1
            uglifyJS: {
                output: {
                    beautify: false, //不需要格式化
                    comments: false, //不保留注释
                },
                compress: {
                    warnings: false, // 在UglifyJs删除没有用到的代码时不输出警告
                    drop_console: true, // 删除所有的 `console` 语句,可以兼容ie浏览器
                    collapse_vars: true, // 内嵌定义了但是只用到一次的变量
                    reduce_vars: true, // 提取出出现多次但是没有定义成变量去引用的静态值
                }
            },
        })

8. Разумное использование sourceMap

9. В сочетании со статистикой для анализа результатов упаковки

10. Компиляция памяти среды разработки

11. Удалите бесполезные плагины в среде разработки


Конфигурация многостраничной упаковки

Настройте html-страницы в нескольких записях и используйте подключаемый модуль HtmlWebpackPlugin, чтобы вставить упакованные j несколько js в соответствующие html-страницы соответственно.

Исходный код хранилища [410

В webpack.common.js:

const path = require('path');
const fs = require('fs');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');
const webpack = require('webpack');


const makePlugins = (configs) => {
	const plugins = [
		new CleanWebpackPlugin(['dist'], {
			root: path.resolve(__dirname, '../')
		})
	];
	Object.keys(configs.entry).forEach(item => {
		plugins.push(
+			new HtmlWebpackPlugin({
				template: 'src/index.html',
				filename: `${item}.html`,
				chunks: ['runtime', 'vendors', item]
			})
		)
	});
	const files = fs.readdirSync(path.resolve(__dirname, '../dll'));
	files.forEach(file => {
		if(/.*\.dll.js/.test(file)) {
			plugins.push(new AddAssetHtmlWebpackPlugin({
				filepath: path.resolve(__dirname, '../dll', file)
			}))
		}
		if(/.*\.manifest.json/.test(file)) {
			plugins.push(new webpack.DllReferencePlugin({
				manifest: path.resolve(__dirname, '../dll', file)
			}))
		}
	});
	return plugins;
}

const configs = {
+	entry: {
		index: './src/index.js',
		list: './src/list.js',
		detail: './src/detail.js',
	},
	resolve: {
		extensions: ['.js', '.jsx'],
	},
	module: {
		rules: [{ 
			test: /\.jsx?$/, 
			include: path.resolve(__dirname, '../src'),
			use: [{
				loader: 'babel-loader'
			}]
		}, {
			test: /\.(jpg|png|gif)$/,
			use: {
				loader: 'url-loader',
				options: {
					name: '[name]_[hash].[ext]',
					outputPath: 'images/',
					limit: 10240
				}
			} 
		}, {
			test: /\.(eot|ttf|svg)$/,
			use: {
				loader: 'file-loader'
			} 
		}]
	},
	optimization: {
		runtimeChunk: {
			name: 'runtime'
		},
		usedExports: true,
		splitChunks: {
      chunks: 'all',
      cacheGroups: {
      	vendors: {
      		test: /[\\/]node_modules[\\/]/,
      		priority: -10,
      		name: 'vendors',
      	}
      }
    }
	},
	performance: false,
	output: {
		path: path.resolve(__dirname, '../dist')
	}
}

configs.plugins = makePlugins(configs);

module.exports = configs

Пятое: базовый принцип Webpack и анализ инструментов формирования шаблонов.

Как написать загрузчик

Исходный код хранилища [51

mkdir make-loader
cd make-loader
npm init -y
npm i webpack webpack-cli -D
npm i loader-utils -D

Создайте папку loaders в корневом каталоге и создайте в ней свой файл loader.js

В webpack.config.js:

const path = require('path');

module.exports = {
	mode: 'development',
	entry: {
		main: './src/index.js'
	},
	resolveLoader: { //先在 node_modules 中找用到的loader,如果没找到,再在loaders里查找
		modules: ['node_modules', './loaders']
	},
	module: {
		rules: [{
			test: /\.js/,
			use: [//使用自己写的replaceLoader
				{
					loader: 'replaceLoader',
				},
				{
					loader: 'replaceLoaderAsync',
					options: {
						name: 'lee'
					}
				},
			]
		}]
	},
	output: {
		path: path.resolve(__dirname, 'dist'),
		filename: '[name].js'
	}
}

Подробности смотрите в официальной документации:loaders#thisquery hiscallback thisasync


Как написать плагин

Исходный код хранилища [52

Подробности смотрите в официальной документации:compiler-hooks


Написание исходного кода бандлера (модульный анализ)

Необходимо для интервью с принципом веб-пакета:

Исходный код хранилища [53

Установить :

//高亮显示代码的工具
npm i cli-highlight -g
//分析源代码
npm install @babel/parser --save
npm install @babel/core --save
npm install @babel/traverse --save
npm install @babel/preset-env --save

Написание исходного кода бандлера (График зависимостей)

Исходный код хранилища [54


Написание исходного кода бандлера (генерация кода)

Исходный код хранилища [55

Шестое: анализ конфигурации инструмента Create-React-App и Vue-Cli 3.0 Scaffolding Tool

Конфигурация Webpack для глубокого обучения с CreateReactApp

Исходный код хранилища [56

Подробности смотрите в официальной документации:CreateReactApp

Быстрый старт:

npx create-react-app my-app
cd my-app
npm start

Скрытые развернутые элементы конфигурации: необратимое действие

npm run eject

Там будет еще две папки, папка config, scripts


Vue-Cli 3.0

Исходный код хранилища [57

Подробности смотрите на официальном сайте:VUE Cli глобальный-cli-конфигурации