Вслед за предыдущей статьейШаг за шагом, чтобы создать большой проект с помощью веб-пакета с нуляВторой после этого. В этой статье используетсяwebpack5
Проект был рефакторинг и используется во всемwebpack-chain
настроитьwebpack
, каждая функция также является отдельным файлом и может использоваться независимо. Так что конфигурацию этого проекта можно использовать в любом проекте. Этот проект может быть использован в реальном бою или в качествеwebpack
Руководство для изучения. Моя цель в разработке этого проекта заключается в том, что вы можете извлечь выгоду из этого, независимо от того, являются ли вы новичком или опытным боссом. Этот проект для желания учитьсяwebpack
Студенты предоставили очень хорошую платформу для реального боя, каждый插件
Каждыйloader
Там будет подробное объяснение и история использования.
Чтобы сэкономить время каждого и повысить эффективность обучения, я хочу поставить всеwebpack
Связанные серии интегрированы здесь.Каждая оптимизация здесь основана на моих неоднократных размышлениях и практике, и я также буду использовать некоторые отличные библиотеки с открытым исходным кодом, чтобы улучшить его.Этот проект будет поддерживаться в течение длительного времени, и все искренне приглашаются к участию в этом проекте, среди которых станьте со-строителями этого проекта вместе!
адрес проекта:GitHub.com/falling snow-Вик Т…
Поскольку в этой статье используетсяwebpack5
Рефакторинг, поэтому сначала поставлю 14-й урок
Содержание этой статьи
- Урок 14: Обновление webpack5
- Тема 10: Добавьте eslint и включите автоисправление
- Тема 11. Добавление stylelint и включение автоматического исправления
- 12 Темы: добавление Цлинта и включить автоматический ремонт
- Проблема 13: Настройка псевдонима
- Урок 15: Определение общих переменных
- Урок 16: Строгая чувствительность пути
- Урок 17: Загрузка ресурсов изображения, svg, мультимедиа, шрифты
- Урок 18: Настройка глобальных стилей
- конфигурация vscode
- более красивая конфигурация
TODO планирую сделать дальшеGitHub.com/falling snow-Вик Т…
Урок 14: Обновление webpack5
Эта глава в основном обновляет проект до webpack5, первый шаг в яме. Поделитесь опытом хождения по яме со всеми.
Webpack5 больше похож на черный ящик: многие задачи, которые раньше приходилось решать с помощью плагинов, теперь интегрированы и используются «из коробки». Основная цель webpack5 — оптимизировать скорость компиляции, добавить больше конфигураций по умолчанию (встроено больше конфигураций), улучшить генерацию кода и проложить путь для дальнейшего развития webpack в будущем.
Краткое содержание этой главы
- Что делает вебпак5?
- обновить веб-пакет5
- Сравнение скорости компиляции
- Изменения с webpack4 на webpack5
Что делает вебпак5?
- Используйте долгосрочный кэш для повышения скорости компиляции
- Улучшите долгосрочное кэширование с помощью лучших алгоритмов и значений по умолчанию.
- Увеличенный размер пакета с улучшенным встряхиванием дерева и генерацией кода
- Рефакторинг внутренних компонентов для реализации функциональности версии 4 без внесения каких-либо критических изменений.
- Подготовьтесь к будущим функциям, внеся критические изменения, чтобы мы могли использовать v5 как можно дольше.
обновить веб-пакет5
В этом учебном пособии можно выполнить обновление/откат одним щелчком мыши с помощью команд создания шаблонов.
webpack-box upgrade 5/4
Два подключаемых модуля были в основном обновлены, а другие используемые модули были совместимы.html-webpack-plugin
Так как плагин предполагает горячее обновление, ошибка горячего обновления еще не исправлена, поэтому все переключаются наwebpack5
Первая компиляция может пройти успешно, но компилятор после сохранения сообщит об ошибке (продолжу обращать внимание, раз ремонт обновляется сразу)
package.json
{
"html-webpack-plugin": "^4.0.0-beta.11",
"webpack": "^5.0.0-beta.9"
}
Сравнение скорости компиляции
webpack-box build index
Version: webpack 4.41.2
Используется следующееcache-loader
- первый раз
4216ms
- второй раз
2781ms
- в третий раз
2827ms
- четвертый раз
2797ms
Version: webpack 5.0.0-beta.9
использовал持久缓存
- первый раз
3567ms
- второй раз
2602ms
- в третий раз
2609ms
- четвертый раз
2582ms
можно увидетьwebpack5
чем использование постоянного кешаwebpack4
Компиляция с cache-loader быстрее100ms ~ 200ms
, поэтому в будущем нет необходимости использовать cache-loader, webpack5 предоставляет лучшие алгоритмы и лучшие решения для кэширования
Изменения с webpack4 на webpack5
1. кеш-загрузчик больше не нужен
При использовании постоянного кеша вам больше не нужен загрузчик кеша. То же, что и в Babel cacheDirectory.
2. Проблема с html-webpack-плагином
некоторые ошибки и исправленияerror
- Cannot add property htmlWebpackPluginAlterChunks, object is not extensible
Установка версии 4.x исправляет это
npm i html-webpack-plugin@4.0.0-beta.11
- Cannot read property 'get' of undefined
未修复
Первая компиляция вступает в силу, и после сохранения будет выдано сообщение об ошибке.webpack5
Горячее обновление было переписано, в результате чегоhtml-webpack-plugin
не совместимы,Причина может быть найдена
3. Динамически загружаемый файл, наконец, имеет имя, но уже не идентификатор, а конкатенацию пути проекта.
Может быть изменен с помощью optimization.chunkIds
Нажмите, чтобы увидеть документацию
module.exports = {
//...
optimization: {
chunkIds: "named"
}
};
// 链式修改
config.optimization.set("chunkIds", "natural");
4. Вложенное встряхивание дерева
Таким образом, в webpack4 a и b будут упакованы в бандл, а webpack5 также удалит вложенный бесполезный код, то есть b не будет упакован в бандл, потому что b не используется.
// inner.js
export const a = 1;
export const b = 2;
// module.js
import * as inner from "./inner";
export { inner };
// user.js
import * as module from "./module";
console.log(module.inner.a);
5. Внутреннее встряхивание модулей
webpack5 проверит, используется ли метод внутри модуля, если он не используется, метод, вызванный внутри модуля, также будет удален.
Но предпосылка в том, что вам нужно знать, что эти коды не имеют побочных эффектов, иначе ваш код, скорее всего, будет удален.Например, если вы хотите написать компонент, но ваша библиотека его не использует, то он может быть запакован по встряхиванию деревьев
Чтобы использовать его, вам нужноpackage.json
Средняя конфигурация"sideEffects": false
, и установитеoptimization.usedExports
правда
// package.json
{
"sideEffects": false
}
// config/optimization.js
config.optimization.usedExports(true);
代码演示
import { something } from "./something";
function usingSomething() {
return something;
}
export function test() {
return usingSomething();
}
Если внешний модуль не использует тестовый метод, то usingSomething что-то тоже будет удалено в бандле
6. Улучшить генерацию кода
Сообщите веб-пакету максимальную версию EcmaScript, чтобы веб-пакет мог генерировать код.
webpack4
Поддерживает только ES5,webpack5
Поддержка ES5 и ES6
ecmaVersion
Диапазон значений 5 ~ 11 или 2009 ~ 2020, для webpack5 по умолчанию установлено минимальное значение 5.
config.output.set("ecmaVersion", 6);
7. SplitChunks and Module Sizes
webpack5 может установить размер упаковки splitChunks в соответствии с различными типами файлов.По умолчанию разделяется и упаковывается только javascript
config.optimization.splitChunks({
minSize: {
javascript: 30000,
style: 50000
}
});
8. Постоянный кеш
webpack5 предоставляет два метода кэширования: один — постоянный кеш для кэширования файлов в файловой системе, другой — кэширование в памяти.
// type {filesystem | memory}
config.cache({
type: "filesystem"
});
По умолчанию он будет кэшироваться вnode_modules/.cache/webpack
, вы можете пройтиcacheDirectory
Возможность изменить каталог кеша
9. Другие
Конкретное содержимое настройки webpack5 нажмите здесь
Тема 10: Добавьте eslint и включите автоисправление
Краткое содержание этой главы
- Извлечено из слоя cwd, одна функция
- Настроить eslint-загрузчик
- функция авторемонта eslint
- Добавить команду строительных лесов
- Используйте компилятор для автоматического исправления
- Проверка фиксации кода (поэтапная проверка)
Извлечено из слоя cwd, одна функция
Цель: чтобы сделать функции более понятными, каждый уровень выполняет только одну функцию и использует стандартизированные API для обработки одной и той же логики.
- PluginAPI обрабатывает логику плагина скаффолдинга
- CommandAPI обрабатывает логику командной строки скаффолдинга
- cwd извлекает командный слой
└── api
│── CommandAPI.js
└── PluginAPI.js
└── cwd
│── build:ssr.js
│── build.js
│── dev.js
│── dll.js
│── lint.js
└── ssr:server.js
Настроить eslint-загрузчик
Настройте eslint-loader, правила eslint будут обнаружены при разработке webpack-box, и если будет ошибка, то она будет отображаться в консоли
config.module
.rule("eslint")
.pre()
.exclude.add(/node_modules/)
.end()
.test(/\.(vue|(j)sx?)$/)
.use("eslint-loader")
.loader(require.resolve("eslint-loader"))
.options({
extensions,
cache: true,
cacheIdentifier,
emitWarning: allWarnings,
emitError: allErrors,
eslintPath: path.dirname(
resolveModule("eslint/package.json", cwd) ||
resolveModule("eslint/package.json", __dirname)
),
formatter: loadModule("eslint/lib/formatters/codeframe", cwd, true)
});
функция авторемонта eslint
Когда наш проект изменит определенное правило, в нашем проекте будет много ошибок.Мы определенно не хотим вручную изменять их одну за другой, поэтому нам нужно использовать функцию автоматического исправления eslint, которая может помочь нам исправить подавляющее большинство ошибок, есть еще некоторые, которые нельзя исправить, и мы можем исправить это вручную.
Часть кода написана здесь, подробнее можно посмотреть в проекте
packages/eslint/lint.js
const { CLIEngine } = loadModule("eslint", cwd, true) || require("eslint");
const config = Object.assign({
extensions,
fix: true,
cwd
});
const engine = new CLIEngine(config);
const defaultFilesToLint = ["src", "tests", "*.js", ".*.js"].filter(pattern =>
globby
.sync(pattern, { cwd, absolute: true })
.some(p => !engine.isPathIgnored(p))
);
const files = args._ && args._.length ? args._ : defaultFilesToLint;
const report = engine.executeOnFiles(files);
if (config.fix) {
CLIEngine.outputFixes(report);
}
Добавить команду строительных лесов
Надеемся исправить в виде командной строки,webpack-box lint eslint
, так и должно бытьcwd
Командная строка добавления слоя
cwd/lint.js
module.exports = function(injectCommand, api) {
injectCommand(function({ program, cleanArgs, boxConfig }) {
program
.command("lint [type]")
.description("修复lint")
.action(async (name, cmd) => {
const options = cleanArgs(cmd);
const args = Object.assign(options, { name }, boxConfig);
require("../build/lint")(args, api);
});
});
};
чтобы мы могли использоватьwebpack-box lint eslint
Исправь большинство ошибок, попробуй~
Используйте компилятор для автоматического исправления
Конечно выполняемwebpack-box lint eslint
Мы можем исправить некоторые ошибки во время выполнения команды, но когда мы пишем код, мы надеемся, что компилятор поможет нам его модифицировать автоматически, вместо того, чтобы ждать написания кода перед проверкой, что принесет нам второстепенные неприятности, и даже будут проблемы, которые не могут быть отремонтированы.вопрос.
Поэтому мы используемvscode
изeslint
Плагины, которые помогут нам достичь этого
Прежде всего, вы должны использовать компилятор vscode, конечно, доступны и другие компиляторы, но здесь мы говорим только о конфигурации vscode.
После того, как вы установили плагин eslint, вам необходимо установить его в настройках"eslint.autoFixOnSave": true
, так что это может быть исправлено автоматически при сохраненииeslint
Ошибка
Конечно, вы, вероятно, использовали его только в этом проекте.eslint
, тогда как в других проектах не требуется исправлять при сохранении
можно добавить в корневой каталог
└── .vscode
└── settings.json
Поместите копию моей собственной конфигурации для справки
{
/*
* @description 编译器配置
* @param tabSize 默认tab为两个空格
* @param formatOnSave 保存时自动修复
*/
"editor.tabSize": 2,
"editor.formatOnSave": true,
/*
* @description eslint 配置
* @param alwaysShowStatus 配置
* @param autoFixOnSave 保存时自动修复
* @param validate 在vue中添加错误提示
*/
"eslint.alwaysShowStatus": true,
"eslint.autoFixOnSave": true,
"eslint.validate": [
"javascript",
"javascriptreact",
{
"language": "vue",
"autoFix": true
}
],
/*
* @description tslint 配置
* @param autoFixOnSave 保存时自动修复
* @param alwaysShowRuleFailuresAsWarnings 所有特征都是用 Warnings
*/
"tslint.autoFixOnSave": true,
"tslint.alwaysShowRuleFailuresAsWarnings": true,
/*
* @description stylelint 配置
* @param autoFixOnSave 保存时自动修复
*/
"stylelint.autoFixOnSave": true,
/*
* @description vetur 配置
*/
"vetur.format.defaultFormatter.html": "prettier",
"vetur.format.defaultFormatterOptions": {
"prettier": {
"semi": false,
"singleQuote": true
}
},
/*
* @description 配置编辑器设置以覆盖某种语言
*/
"[typescript]": {
// "editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "eg2.tslint"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[vue]": {
"editor.defaultFormatter": "eg2.tslint"
},
"[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
Проверка фиксации кода (поэтапная проверка)
Вышеупомянутые операции — это все проверки и ремонт в нашем идеальном состоянии, но иногда возникают непредвиденные ситуации, и код lint не отправляется, что может вызвать проблемы, поэтому нам необходимо выполнить проверку кода перед отправкой кода.
Добавьте lint-staged в package.json, lint будет выполняться первым при отправке кода, а отправка будет успешной после передачи lint
package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,jsx}": ["webpack-box lint eslint", "git add"]
}
}
Тема 11. Добавление stylelint и включение автоматического исправления
Краткое содержание этой главы
- Настройка стандартного плагина stylelint
- Настройте плагин stylelint
- авто ремонт
- проверка фиксации кода
Настройка стандартного плагина stylelint
Используйте стандартный плагин stylelint-config
.stylelintrc.js
module.exports = {
root: true,
extends: "stylelint-config-standard"
};
Настройте плагин stylelint
module.exports = ({
config,
options: { stylelint: { lintOnSave = false, extensions } = {} },
api
}) => {
const StyleLintPlugin = require("stylelint-webpack-plugin");
const CodeframeFormatter = require("stylelint-codeframe-formatter");
const stylelint = [];
return () => {
config.plugin("stylelint").use(StyleLintPlugin, [
Object.assign(
{
failOnError: lintOnSave === "error",
files: ["src/**/*.{vue,htm,html,css,sss,less,scss}"],
formatter: CodeframeFormatter
},
stylelint
)
]);
};
};
авто ремонт
module.exports = async function lint({ api, args = {}, pluginOptions = {} }) {
const cwd = api.resolve(".");
const files =
args._ && args._.length
? args._
: [cwd + "/src/**/*.{vue,htm,html,css,sss,less,scss}"];
if (args["no-fix"]) {
args.fix = false;
delete args["no-fix"];
}
const { formatter } = args;
if (
formatter &&
typeof formatter === "string" &&
!["json", "string", "verbose"].includes(formatter)
) {
try {
args.formatter = require(formatter);
} catch (e) {
delete args.formatter;
if (typeof pluginOptions.formatter !== "function") {
console.log(
format(
chalk`{bgYellow.black WARN }`,
chalk`${e.toString()}\n{yellow Invalid formatter}`
)
);
}
}
}
const options = Object.assign(
{},
{
configBasedir: cwd,
fix: true,
files,
formatter: CodeframeFormatter
},
pluginOptions,
normalizeConfig(args)
);
try {
const { errored, results, output: formattedOutput } = await stylelint.lint(
options
);
if (!errored) {
if (!args.silent) {
const hasWarnings = results.some(result => {
if (result.ignored) {
return null;
}
return result.warnings.some(
warning => warning.severity === "warning"
);
});
if (hasWarnings) {
console.log(formattedOutput);
} else {
console.log(
format(
chalk`{bgGreen.black DONE }`,
`stylelint 没有发现错误!${
options.fix ? chalk` {blue (已经自动修复)}` : ""
}`
)
);
}
}
} else {
console.log(formattedOutput);
process.exit(1);
}
} catch (err) {
console.log(
format(chalk`{bgRed.black ERROR }`, err.stack.slice(" Error:".length))
);
process.exit(1);
}
};
проверка фиксации кода
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{vue,htm,html,css,sss,less,scss}": [
"webpack-box lint stylelint",
"git add"
],
"*.{js,jsx}": ["webpack-box lint eslint", "git add"]
}
}
Тема 12. Добавление tslint и включение автоматического исправления
Краткое содержание этой главы
Настроить плагин
config/tslintPlugin.js
module.exports = ({
config,
options: { tslint: { lintOnSave = false, useThreads = false } = {} },
api
}) => {
const fs = require("fs");
return () => {
config.plugin("fork-ts-checker").tap(([options]) => {
options.tslint =
lintOnSave !== false && fs.existsSync(api.resolve("tslint.json"));
options.formatter = "codeframe";
options.checkSyntacticErrors = useThreads;
return [options];
});
};
};
добавить правило
tslint.json
{
"defaultSeverity": "warning",
"extends": ["tslint:recommended"],
"linterOptions": {
"exclude": ["node_modules/**"]
},
"rules": {
"max-classes-per-file": [true, 5, "exclude-class-expressions"],
"quotemark": [true, "single"],
"semicolon": [true, "never"],
"indent": [true, "spaces", 2],
"ordered-imports": false,
"object-literal-sort-keys": false,
"no-consecutive-blank-lines": false,
"disable-next-line": false,
"only-arrow-functions": false,
"radix": false,
"class-name": false,
"eofline": false,
"no-unused-expression": false,
"no-console": false,
"trailing-comma": false,
"interface-name": false
}
}
функция авторемонта
const { done } = require("@vue/cli-shared-utils");
module.exports = function lint({ args = {}, api, silent }) {
const options = {
fix: args.fix !== false,
formatter: args.format || "codeFrame",
formattersDirectory: args["formatters-dir"],
rulesDirectory: args["rules-dir"]
};
const program = tslint.Linter.createProgram(api.resolve("tsconfig.json"));
const linter = new tslint.Linter(options, program);
const updateProgram = linter.updateProgram;
linter.updateProgram = function(...args) {
updateProgram.call(this, ...args);
patchProgram(this.program);
};
const tslintConfigPath = tslint.Configuration.CONFIG_FILENAMES.map(filename =>
api.resolve(filename)
).find(file => fs.existsSync(file));
const config = tslint.Configuration.findConfiguration(tslintConfigPath)
.results;
const lint = file => {
const filePath = api.resolve(file);
const isVue = isVueFile(file);
patchWriteFile();
linter.lint(filePath, "", isVue ? vueConfig : config);
restoreWriteFile();
};
const files =
args._ && args._.length
? args._
: [cwd + "/src/**/*.ts", cwd + "/src/**/*.vue", cwd + "/src/**/*.tsx"];
return globby(files, { cwd }).then(files => {
files.forEach(lint);
if (silent) return;
const result = linter.getResult();
if (result.output.trim()) {
process.stdout.write(result.output);
} else if (result.fixes.length) {
const f = new tslint.Formatters.ProseFormatter();
process.stdout.write(f.format(result.failures, result.fixes));
} else if (!result.failures.length) {
done("tslint 没有发现错误.\n");
}
if (result.failures.length && !args.force) {
process.exitCode = 1;
}
});
};
Отправить на проверку
{
"lint-staged": {
"*.{vue,htm,html,css,sss,less,scss}": [
"webpack-box lint stylelint",
"git add"
],
"*.{ts,tsx}": ["webpack-box lint tslint", "git add"],
"*.{js,jsx}": ["webpack-box lint eslint", "git add"]
}
}
Тема 13: Настройка псевдонимов
В нашей работе, если файл нужно скопировать в другой каталог, ссылка на этот файл может иметь ошибку пути. Кроме того, нам не нравится искать каждый раз, когда мы импортируем зависимости, мы хотим иметь возможность иметь псевдоним для указания определенного каталога, независимо от того, где мы его используем.
Краткое содержание этой главы
- Использовать псевдонимы в проектах
- Настроить псевдонимы
- реализация веб-пакета
- Конфигурация перехода компилятора
Использовать псевдонимы в проектах
src/main.js
import { cube } from "./treeShaking";
import { cube } from "@/treeShaking";
import { cube } from "@src/treeShaking";
Настроить псевдонимы
alias: {
'@': resolve('src'),
'@src': resolve('src')
}
реализация веб-пакета
module.exports = ({ config, options, resolve }) => {
const fs = require("fs");
const conf = options.alias;
return () => {
// 生成默认别名
const dirs = fs.readdirSync(resolve("src"));
let aliasConfig = config.resolve.extensions
.merge([".mjs", ".js", ".jsx", ".vue", ".ts", ".json", ".wasm"])
.end().alias;
dirs.forEach(v => {
const stat = fs.statSync(resolve(`src/${v}`));
if (stat.isDirectory()) {
aliasConfig = aliasConfig.set(`@${v}`, resolve(`src/${v}`));
}
});
// 用户配置别名
if (conf.alias) {
const keys = Object.keys(conf.alias);
keys.forEach(key => {
aliasConfig = aliasConfig.set(key, conf.alias[key]);
});
}
// 自定义设置别名
aliasConfig.set("@", resolve("src")).set("@src", resolve("src"));
};
};
Конфигурация перехода компилятора
Если вы используете ts, то после настройки алиаса тип будет потерян, указывая на то, что модуль не может быть найден, поэтому нам нужно настроить соответствующий алиас в компиляторе.
tsconfig.json/jsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"rootDir": ".",
"paths": {
"@src/*": [
"src/*"
],
"@/*": [
"src/*"
],
}
}
}
Урок 15: Определение общих переменных
Иногда нам нужен мост связи между скаффолдингом и бизнес-кодом.
как мыnpm run build
Когда мы запускаем производственную среду, я хочуmain.js
Выполните специальную логику в производственной среде. ноmain.js
Выполнение находится на стороне браузера, в то время какnpm run build
при беге наnode
Два конца не могут общаться. Так что же нам делать?
webpack
предоставляет нам плагинEnvironmentPlugin
, этот плагин позволяет намnode
сторонние переменные, значение компилируется в код во время компиляции, например
мы вmain.js
написал абзацnode
, но это не распознается в браузере, потому что браузер неprocess
Object, этот код без происшествий сообщит об ошибке
main.js
if (process.env.NODE_ENV === "production") {
console.log("Welcome to production");
}
мы настраиваемwebpack.EnvironmentPlugin
плагин
const webpack = require("webpack");
module.exports = ({ config, resolve, options }) => {
return () => {
const resolveClientEnv = require("../util/resolveClientEnv");
config
.plugin("process-env")
.use(webpack.EnvironmentPlugin, [resolveClientEnv(options)]);
};
};
util/resolveClientEnv.js
module.exports = function resolveClientEnv(options, raw) {
const env = {};
if (process.env) {
Object.keys(process.env).forEach(key => {
if (key === "NODE_ENV") {
env[key] = process.env[key];
}
});
}
if (options.env) {
Object.assign(env, options.env);
}
return env;
};
мы выступаемnpm run build
,посмотриdist/index.bundle.js
во что будет компилироваться
// "production" === "production"
if (true) {
console.log("Welcome to production");
}
webpack
Будуprocess.env.NODE_ENV
Значение скомпилировано вbundle
, то что мы можемweb
Терминал запущен и скомпилирован в рабочей среде.
Урок 16: Строгая чувствительность пути
Иногда у нас часто возникает такая ситуация, очевидно, что с локальной компиляцией проблемы нет, но при онлайн-компиляции Jenkins будет сообщено об ошибке. Появился локальный путь Проблема, наш локальный нечувствителен к регистру при заключении путей в кавычки. Например
└──── src
│── Index.js
└── main.js
Первая буква Index.js в указанном выше пути написана заглавной, но я ссылаюсь на нее строчными буквами в main.js.
main.js
import Index from "./index.js";
Это не сообщит об ошибке локально, но когда вы выйдете в Интернет с помощью Jenkins, вы сообщите об ошибке, что модуль ./index.js не может быть найден.
Так что нам нужен плагин, который строго проверяет регистр при разработке, чтобы не было таких проблем.
Мы используемcase-sensitive-paths-webpack-plugin
плагин для его реализации
module.exports = ({ config, webpackVersion, resolve, options }) => {
return () => {
// webpack 5 不兼容
if (parseInt(webpackVersion) >= 5) return;
config
.plugin("case-sensitive-paths")
.use(require("case-sensitive-paths-webpack-plugin"));
};
};
Урок 17: Загрузка ресурсов изображения, svg, мультимедиа, шрифты
Эта глава перейдет непосредственно к коду, который является дополнением к предыдущей основной главе.
module.exports = ({ config, webpackVersion, resolve, options }) => {
return () => {
const getAssetPath = require("../util/getAssetPath");
const inlineLimit = 4096;
const genAssetSubPath = dir => {
return getAssetPath(
options,
`${dir}/[name]${options.filenameHashing ? ".[hash:8]" : ""}.[ext]`
);
};
const genUrlLoaderOptions = dir => {
return {
limit: inlineLimit,
fallback: {
loader: "file-loader",
options: {
name: genAssetSubPath(dir)
}
}
};
};
config.module
.rule("images")
.test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
.use("url-loader")
.loader(require.resolve("url-loader"))
.options(genUrlLoaderOptions("img"));
config.module
.rule("svg")
.test(/\.(svg)(\?.*)?$/)
.use("file-loader")
.loader(require.resolve("file-loader"))
.options({
name: genAssetSubPath("img")
});
config.module
.rule("media")
.test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/)
.use("url-loader")
.loader(require.resolve("url-loader"))
.options(genUrlLoaderOptions("media"));
config.module
.rule("fonts")
.test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i)
.use("url-loader")
.loader(require.resolve("url-loader"))
.options(genUrlLoaderOptions("fonts"));
};
};
Урок 18: Настройка глобальных стилей
При написании css мы инкапсулируем часто используемые функции/переменные в файл global.less/scss, а затем импортируем его при использовании. Очевидно, что импорт вручную каждый раз становится очень хлопотным и подверженным ошибкам (особенно, когда в группу приходят новые люди), поэтому мы подумали, что было бы идеально, если бы мы автоматически вводили global в файл?
нам нужноstyle-resources-loader
чтобы помочь нам сделать это
Настроить загрузчик стилей-ресурсов
config/styleResourceLoader.js
module.exports = ({ config, options }) => {
const resourcesOpt = options.resources;
return () => {
["normal"].forEach(oneOf => {
Object.keys(resourcesOpt).forEach(loader => {
config.module
.rule(loader)
.oneOf(oneOf)
.use("style-resources-loader")
.loader("style-resources-loader")
.options({
patterns: resourcesOpt[loader].patterns
});
});
});
};
};
config/style.js
if (loader) {
let resolvedLoader;
try {
resolvedLoader = require.resolve(loader);
} catch (error) {
resolvedLoader = loader;
}
rule
.use(loader)
.loader(resolvedLoader)
// options 是对应 config 中的 css 参数,可以自行配置对应loader的参数
.options(Object.assign({ sourceMap }, options));
}
Конфигурация проекта
box.config.js
{
"css": {
"sourceMap": true, // 是否开启css source map
"loaderOptions": { // 配置loader的options
"css": {},
"less": {
"globalVars": { // less 设置全局变量
"gray": "#ccc"
}
},
"sass": {},
"postcss": {},
"stylus": {}
},
"isCssModule": false, // 是否对css进行模块化处理
"needInlineMinification": false // 是否需要压缩css
},
"resources": {
"less": {
"patterns": [path.resolve(__dirname, "./src/global/*.less")]
},
"scss": {
"patterns": [path.resolve(__dirname, "./src/global/*.scss")]
}
}
}
использовать
└──── src
│── global
│ │── index.less
│ └── index.scss
└── style
└── index.less
установить глобальный стиль
global/index.less
.g-less-height () {
height: 100%;
}
.g-less-test {
width: 100%;
}
Используйте глобальные стили
style/index.less
.test {
width: 300px;
color: @gray;
.g-less-height();
}
style/index.scss
.g-scss-test {
width: 100%;
}
после компиляции
dist/css/index.css
.g-less-test {
width: 100%;
}
.test {
color: #ccc;
width: 100%;
height: 100%;
}
.g-scss-test {
width: 100%;
}
Видимые глобальные стили упакованы вdist/css/index.css
В, нам больше не нужно вручную импортировать каждый раз
конфигурация vscode
Поместите его в корневой каталог и включите функцию автоматического восстановления eslint/tslint/stylelint.
.vscode/setting.json
{
/*
* @description 编译器配置
* @param tabSize 默认tab为两个空格
* @param formatOnSave 保存时自动修复
*/
"editor.tabSize": 2,
"editor.formatOnSave": true,
/*
* @description eslint 配置
* @param alwaysShowStatus 配置
* @param autoFixOnSave 保存时自动修复
* @param validate 在vue中添加错误提示
*/
"eslint.alwaysShowStatus": true,
"eslint.autoFixOnSave": true,
"eslint.validate": [
"javascript",
"javascriptreact",
{
"language": "vue",
"autoFix": true
}
],
/*
* @description tslint 配置
* @param autoFixOnSave 保存时自动修复
* @param alwaysShowRuleFailuresAsWarnings 所有特征都是用 Warnings
*/
"tslint.autoFixOnSave": true,
"tslint.alwaysShowRuleFailuresAsWarnings": true,
/*
* @description stylelint 配置
* @param autoFixOnSave 保存时自动修复
*/
"stylelint.autoFixOnSave": true,
/*
* @description vetur 配置
*/
"vetur.format.defaultFormatter.html": "prettier",
"vetur.format.defaultFormatterOptions": {
"prettier": {
"semi": false,
"singleQuote": true
}
},
/*
* @description 配置编辑器设置以覆盖某种语言
*/
"[typescript]": {
// "editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "eg2.tslint"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[vue]": {
"editor.defaultFormatter": "eg2.tslint"
},
"[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
более красивая конфигурация
Сделайте что-нибудь с lint, форматированием в стиле кода
prettier.config.js
/**
* pretiier 标准配置
*/
module.exports = {
// 在ES5中有效的结尾逗号(对象,数组等)
trailingComma: "es5",
// 不使用缩进符,而使用空格
useTabs: false,
// tab 用两个空格代替
tabWidth: 2,
// 仅在语法可能出现错误的时候才会添加分号
semi: false,
// 使用单引号
singleQuote: true,
// 在Vue文件中缩进脚本和样式标签。
vueIndentScriptAndStyle: true,
// 一行最多 100 字符
printWidth: 100,
// 对象的 key 仅在必要时用引号
quoteProps: "as-needed",
// jsx 不使用单引号,而使用双引号
jsxSingleQuote: false,
// 大括号内的首尾需要空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
// 箭头函数,只有一个参数的时候,也需要括号
arrowParens: "always",
// 每个文件格式化的范围是文件的全部内容
rangeStart: 0,
rangeEnd: Infinity,
// 不需要写文件开头的 @prettier
requirePragma: false,
// 不需要自动在文件开头插入 @prettier
insertPragma: false,
// 使用默认的折行标准
proseWrap: "preserve",
// 根据显示样式决定 html 要不要折行
htmlWhitespaceSensitivity: "css",
// 换行符使用 lf
endOfLine: "lf"
};
Суммировать
На данный момент webpack series 2 закончился, а самое интересное еще впереди.Первые две статьи можно рассматривать только как основу для более поздних больших проектов.В дальнейшем буду использовать lerna для рефакторинга,использую plug - в управлении и построить подключаемую экологическую систему. Проекты Vue и React будут построены позже, и даже небольшие программы, кросс-энд и т. д. будут интегрированы.
Здесь вы можете разместить свои мыслиGitHub.com/falling snow-Вик Т…Я серьезно отнесусь к каждому вопросу