Migracja dodatku Ember do formatu v2
W drodze do edycji Polaris ogłoszono jedną dużą zmianę w świecie Ember JS: Embroider, system kompilacji nowej generacji, który ma na celu wypełnienie luki między Ember a szerszym ekosystemem JS, przynosząc wiele korzyści po jego przyjęciu. Jak wspomniano w RFC :
- mniej „specjalnych” dodatków, które będą zwykłymi pakietami NPM
- szybsze kompilacje i instalacje NPM.
- możliwość wykorzystania istniejących narzędzi do budowania, takich jak Webpack lub Vite
- wprowadzając ważne funkcje, których brakowało ekosystemowi Ember przez zbyt długi czas, takie jak potrząsanie drzewem i dzielenie kodu
Kontekst
Dodatek, nad którym pracowałem, zawiera następujące funkcje:
- Maszynopis
- Usługi
- Adaptery Ember Data, modele, serializatory
- Komponenty (mieszanka Glimmer i Ember Classic)
- Tłumaczenia (obsługiwane przez ember-intl )
- Niektóre zasoby publiczne (obrazy) używane w komponentach, które należy skopiować do aplikacji nadrzędnych
- Niektóre CSS (wstępnie przetworzone przy użyciu Less )
Ponadto po raz pierwszy musiałem pracować z monorepos (tutaj Yarn Workspaces), więc niektóre problemy, z którymi się spotkałem, mogą być związane z moim brakiem wiedzy na ich temat.
Uruchamianie codemoda
Jeśli jeszcze tego nie zrobiłeś, gorąco polecam przeczytanie przewodnika migracji dotyczącego przenoszenia dodatków v1 do formatu v2, ponieważ zawiera on wiele wyjaśnień na temat nowego drzewa plików.
Na szczęście, odkąd wprowadzono format v2, społeczność napisała kilka modów kodowych, aby przyspieszyć ten proces, a ja wybrałem ember-codemod-v1-to-v2 ( ember-addon-migrator jest również opcją, ale zrobiłem to jeszcze nie testowalem).
npx [email protected] --addon-location="packages/addon" --test-app-location="packages/test-app"
- pakiet dodatku: to jest rzeczywisty kod twojego dodatku, który spodziewasz się przekazać aplikacjom nadrzędnym
- pakiet aplikacji testowej pełniący tę samą rolę, co fikcyjna aplikacja w formacie v1.
- zbuduj dodatek (w tym w trybie oglądania)
- uruchom testowy serwer aplikacji
- uruchom testy w aplikacji testowej
Radzenie sobie z tłumaczeniami
translationsKorzystając z ember-intl, w katalogu głównym projektu znajduje się katalog , który został pominięty przez codemod, co prowadzi do brakujących tłumaczeń w razie potrzeby. Aby to naprawić, musiałem po prostu przenieść translationskatalog do katalogu głównego pakietu dodatku, a następnie wyświetlić go w polu „pliki”, packages/my-addon/package.jsonaby został opublikowany i udostępniony aplikacjom nadrzędnym.
{
"name": "my-addon",
"version": "0.0.13",
"keywords": [
"ember-addon"
],
...,
"files": [
"addon-main.cjs",
"dist",
"translations"
]
}
Ponieważ dodatek jest dostarczany z adapterami Ember Data, należy je skonfigurować tak, aby trafiały do właściwego hosta zaplecza w zależności od działającego środowiska aplikacji nadrzędnej.
Wcześniej zrobilibyśmy to tak:
import { getOwner } from '@ember/application';
export default class BaseAdapter extends AuthorizedAdapter {
get namespace(): string {
return 'api/v1';
}
get host(): string {
const config = getOwner(this).resolveRegistration('config:environment')['my-addon'];
return config.backendURL;
}
}
Niestety to już nie działało, ponieważ w formacie v2 chodzi o mniej magii i mniej magii czasu kompilacji. Ale nadal jest to możliwe przy użyciu @embroider/macros. Korzystając z tego pakietu, mogłem skonfigurować odpowiedniego hosta, po prostu aktualizując configwartość obiektu:
import { getOwnConfig } from '@embroider/macros';
export default class BaseAdapter extends AuthorizedAdapter {
get namespace(): string {
return 'api/v1';
}
get host(): string {
return (getOwnConfig() || {}).backendURL;
}
}
module.exports = function (defaults) {
let app = new EmberAddon(defaults, {
'@embroider/macros': {
setConfig: {
'my-addon': {
backendURL: process.env.BACKEND_URL || 'https://some-default.api.io'
}
}
}
});
}
Dostarczanie majątku publicznego
Po połączeniu dodatku w aplikacji, która faktycznie go używa, zauważyłem, że wszystkie obrazy, które zwykle są z nim dostarczane, nie były obecne w kompilacji aplikacji.
Okazuje się, że pliki w folderze dodatku (który , nawiasem mówiąc, publicnależy przenieść do ) muszą być wymienione w metaobiekcie dodatku w następującym formacie:packages/my-addon/publicpackage.jsonember-addon.public-assets
{
"name": "my-addon",
"version": "0.0.13",
"keywords": [
"ember-addon"
],
"ember-addon": {
...,
"public-assets": {
"./public/assets/images/tomster.png": "/my-addon/assets/images/tomster.png",
"./public/assets/images/zoey.svg": "/my-addon/assets/images/zoey.svg"
}
}
...
}
Jednakże, chociaż może to być dość szybkie w przypadku dodatku, który zapewnia tylko kilka zasobów publicznych, może wymknąć się spod kontroli, jeśli jest ich wiele, więc istnieje otwarte żądanie ściągnięcia, aby dodać wbudowaną wtyczkę Rollup , która utrzymuje ember-addon.public-assetssynchronizację obiektu meta z publickatalogiem.
Obsługa CSS
Jak wspomniano wcześniej, ten dodatek zapewnia niektóre komponenty wraz z ich CSS, wstępnie przetworzone przy użyciu Less CSS. Nie miałem też wcześniej komponentów importujących własny CSS, ale raczej plik punktu wejścia, addon/styles/addon.lessktóry importował inne względne pliki. Aby uniknąć przechodzenia przez wszystkie komponenty i kolokacji ich CSS obok nich, zdecydowałem się na razie kontynuować z jednym plikiem CSS. W tym momencie miałem więc dwie sprawy do załatwienia:
- CSS, który nie został zaimportowany z pliku JS, zostanie pominięty
ember-cli-lessnie działał już do obsługi plików Less
{
"name": "my-addon",
"version": "0.0.13",
"keywords": [
"ember-addon"
],
...,
"exports": {
".": "./dist/index.js",
"./*": {
"types": "./dist/*.d.ts",
"default": "./dist/*.js"
},
"./addon-main.js": "./addon-main.cjs",
"./styles": "./dist/styles/_addon.css",
},
}
import Application from '@ember/application';
import Resolver from 'ember-resolver';
import loadInitializers from 'ember-load-initializers';
import config from './config/environment';
import 'my-addon/styles';
export default class App extends Application {
modulePrefix = config.modulePrefix;
Resolver = Resolver;
}
loadInitializers(App, config.modulePrefix);
- w przypadku refaktoryzacji: masz wszystko obok siebie
- ułatwia potrząsanie drzewem i nie wysyła martwego kodu CSS do przeglądarki
import { readFileSync, writeFileSync } from 'fs';
import less from 'less';
import { Addon } from '@embroider/addon-dev/rollup';
const addon = new Addon({
srcDir: 'src',
destDir: 'dist'
});
export default {
// This provides defaults that work well alongside `publicEntrypoints` below.
// You can augment this if you need to.
output: addon.output(),
plugins: [
// Made sure to do the preprocessing before the keepAssets plugin is ran.
{
name: 'less-handler',
generateBundle() {
const lessCode = readFileSync('src/styles/main.less', 'utf-8');
less.render(
lessCode,
{
paths: ['src/styles']
},
(err, rendered) => {
if (err) {
console.log(err);
return;
}
const css = rendered.css;
const filename = path.join('src', 'styles', '_addon.css');
mkdirp.sync(path.dirname(filename));
writeFileSync(filename, css);
}
);
}
},
// addons are allowed to contain imports of .css files, which we want rollup
// to leave alone and keep in the published output.
addon.keepAssets(['**/*.css']),
// Remaining plugins from the sample file
]
};
Rozwiązywanie problemów
Oto kilka problemów, które można było łatwo naprawić po uruchomieniu codemoda:
- deklarowane pola muszą najpierw zostać przekształcone przez @babel/plugin-transform-typescript. Naprawiono poprzez włączenie
allowDeclareFieldsopcji (https://babeljs.io/docs/babel-preset-typescript#allowdeclarefields) - Podczas zastępowania starych importów (z nazwą pakietu jako root) importami względnymi, codemod przypadkowo zastąpił dynamicznie budowane ścieżki zasobów w niektórych komponentach importami względnymi, psując niektóre ścieżki obrazów. W tym miejscu może być potrzebne szybkie podwójne sprawdzenie
- ember-auto-import
css-loadernie obsłużyło adresów URL ze ścieżkami względnymi. Jest to znany problem z Webpackiem, który miałem nawet poza tym kontekstem migracji. Na razie ustawienieautoImport.cssLoaderOptions.urlnafalse(por.https://webpack.js.org/loaders/css-loader/#url) rozwiązuje problem.

![Czym w ogóle jest lista połączona? [Część 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































