Поиск по метке: JavaScript
How to migrate Javascript webpack configuration to Typescript
It turned out that the newest versions (at least 5+) of webpack support Typescript out of the box. So the algorithm is next:
- Create tsconfig.json at the root level. Content:
{ "compilerOptions": { "module": "CommonJS", "target": "ES5", "esModuleInterop": true, "checkJs": false, "strict": true, } }
- Rename all *.js files to *.ts
- Type all of them:
- no more ugly require, use import.
- webpack package has typings out of the box.
- You may find these types useful: Configuration & RuleSetRule
- To enable devServer write this:
interface Configuration extends WebpackConfiguration { devServer?: WebpackDevServerConfiguration; }
- Some of the popular plugins have types too.
- Some of them don't have types at all:
- Create a *.d.ts file
- Put there something like this:
declare module 'postcss-assets' { export default function postcssAssets(opts: { basePath: string; relative: boolean; }): unknown; }
- Make sure your webpack.config.ts file is placed at the root level. I mean exactly at the same spot where node_modules is. Otherwise, you won't be able to build it. No compilerOptions helped me.
- Run webpack. It should work.
Multilayout Keybinds in a Browser
Imagine that you want to add support of some keybinds in your web application. Let it be Ctrl+L for liking\unliking something. What kind of issues can you face in such a scenario?
CMD or Ctrl?
At first look at Ctrl. Probably on MacOS you'd like to replace it with CMD. You can check it by event.metaKey.
Extra modificators
Probably you wouldn't like to consider Ctrl+Alt+S as Ctrl+S. So don't forget to handle this case.
Different layouts
Not every language that uses the Latin alphabet has the L button at the same position as in a typical English keyboard layout. You need to decide what is more important to you ― a real key position on a keyboard or a letter upon of it. I'd guess that the 2nd case is preferable for most applications.
To get a real key position you can use which, code, codeKey properties. To get a letter on the key use key property.
Different alphabets
What's about Greek or Russian alphabets? Or any other possible alphabets? Or not even alphabets? There're different strategies. And one of them is to use a key from a typical English keyboard layout. So it leads us again to code and codeKey properties.
Example
const getEventKeyBind = event => {
const keybind = [];
if (event.metaKey) keybind.push('cmd');
if (event.ctrlKey) keybind.push('ctrl');
if (event.shiftKey) keybind.push('shift');
if (event.altKey) keybind.push('alt');
if (event.key === ' ') keybind.push('space');
else {
const key = event.key.toLowerCase();
if (key.length !== 1 || key.match(/^[a-z]$/)) {
// latin key or a special key
keybind.push(key);
} else {
// extra-latin or non-latin key
const [, enSymbol] = event.code.match(/^Key(\w)$/) || [];
keybind.push(enSymbol ? enSymbol.toLowerCase() : key);
}
}
return keybind.join('+');
};
Отладка NodeJS приложений при помощи ndb
Пост-заметка об ndb. Всем кто пишет для nodejs периодически приходится отлаживать своё приложение. Да даже тем, кто использует mocha или webpack бывает нет-нет да удобнее отладить по-человечески проблему, нежели тыкать повсюду console.log-и. NodeJS издавна предоставляет нам для этого браузерный инструмент.
Работает оно так:
- мы запускаем наше приложение из консоли с нужным флагом
- NodeJS в консоли нам сообщает ссылку с нужным портом
- Которую мы открываем в браузере и видим перед собой копию chrome-dev-tools-ов.
Если надо перезагрузить приложение ― повторяем всё с нуля. С одной стороны сами инструменты весьма удобные. С другой стороны вся эта мышиная возня с портами и перезапусками очень неудобна.
И тут на помощь к нам приходит ndb. Просто перед командой запуска приложения добавляем ndb. Dev-tools-ы открываются прямо в своём отдельном окне. Перезагрузить приложение можно нажав ctrl+R. Все breakpoint-ы и прочая муть при этом сохраняется.
Выглядит это всё примерно так:
Webpack и SCSS импорты в купе с module-resolver
С приходоим ES7 в JS пришли import-ы и export-ы. Жить стало веселее, и... сложнее. Появилось много заморочек и вообще новых проблем. Одна из таких проблем выглядит так: `import some from ../../../../../some`. Знакомая ситуация?
Обычно её в случае webpack-а решают при помощи модуля module-resolver. Он позволяет в .babelrc (или где вы держите конфигурацию) указывать регулярные выражения для автозамены, а также добавляет поддержку root-записей. Скажем с ним можно указать `import actions from '@actions/header', где `@actions` будет алиасом к какому-нибудь пути в вашем проекте.
Дальше встаёт вопрос инструментов. А как на это должен реагировать редактор? Как он узнает, что теперь пути в import-ах устроены хитрее. Что делать с линтингом? К счастью, для eslint есть такой плагин: eslint-plugin-import. С редакторами ситуация может быть сложнее.
Хорошо, а что делать с SCSS\Sass? Нормальных рабочих решений с наскоку мне найти не удалось. Но как оказалось, всё можно решить относительно просто. В настройках webpack для sass-loader-а можно указать настройки. Они будут переданы как есть в пакет node-sass. А вот он, оказывается, достаточно гибкий. Если там указать метод importer, то можно навязать свою логику обработки @import-ов. Пример:
{
loader: 'sass-loader',
options:
{
sourceMap: true,
url: false,
importer: url => (
{
file: url
.replace(...)
.replace(...)
.replace(...),
}),
},
}
Либо даже выцепить ваши настройки прямо из настроек в .babelrc.
Embedded webpack application
Возникла необходимость внедрять готовый SPA в другой проект на страницу. Проект сразу писался под это дело, но всё равно возник ряд проблем, которые нужно было решать. Напишу про 2 из них сюда как шпаргалку.
webpack & dynamic import
Что если ваш проект использует динамический импорт? Например System.import. В этом случае webpack сделает для подгружаемых файлов отдельный chunk. И грузить он его будет исходя из publicPath в настройках webpack. Но ведь embedded решения могут быть внедрены по любому пути. Как быть? Всё просто, пишем в точке входа что-нибудь типа: __webpack_public_path__ = window.myPredefinedPath и дело в шляпе. Магия. До загрузки приложения нужно определить этот window.myPredefinedPath, webpack его увидит и будет использовать. Сразу отмечу, что надо писать как есть, не window.__webpack...=, а как-будто эта переменная уже определена в коде. Если на неё ругается eslint не беда, пишем: // eslint-disable-line и он более не ругается.
webpack css & url
Возникла проблема с тем, что в стилях указаны пути к шрифтам так, что webpack их найти не может (отдельная тема почему так). Да и не должен, него его это забота. Однако он пытается от-revolve-ить все пути, что находит в css. Лечится установкой url: false в cssLoader-е. После этой настройки пути отдаются как есть без каких-либо проверок.