Ember 애드온을 v2 형식으로 마이그레이션
Polaris 에디션으로 가는 길에 Ember JS 세계에서 한 가지 주요 변경 사항이 발표되었습니다. Embroider는 Embroider와 더 넓은 JS 생태계 사이의 격차를 해소하는 것을 목표로 하는 차세대 빌드 시스템으로 일단 채택되면 많은 이점을 제공합니다. RFC 에서 언급한 바와 같이 :
- 일반적인 NPM 패키지가 될 "특별한" 애드온이 적습니다.
- 더 빠른 빌드 및 NPM 설치.
- Webpack 또는 Vite와 같은 기존 빌드 도구를 활용할 수 있습니다.
- 나무 흔들기 및 코드 분할과 같이 Ember 생태계에 너무 오랫동안 부족했던 중요한 기능을 제공합니다.
문맥
내가 작업한 애드온에는 다음과 같은 기능이 포함되어 있습니다.
- 타자기
- 서비스
- Ember 데이터 어댑터, 모델, 직렬 변환기
- 구성 요소(Glimmer와 Ember Classic의 혼합)
- 번역( ember-intl 제공 )
- 상위 앱에 복사해야 하는 구성 요소에 사용되는 일부 공용 자산(이미지)
- 일부 CSS( Less 를 사용하여 전처리됨 )
또한 monorepos(여기서는 Yarn Workspaces)로 작업해야 하는 것이 이번이 처음이었기 때문에 내가 직면한 문제 중 일부는 이에 대한 지식 부족과 관련이 있을 수 있습니다.
코드모드 실행
아직 완료하지 않은 경우 새 파일 트리에 대한 많은 설명을 제공하는 v1 애드온을 v2 형식으로 포팅하기 위한 마이그레이션 가이드를 읽어 보시기 바랍니다 .
다행스럽게도 v2 형식이 도입된 이후로 프로세스 속도를 높이기 위해 커뮤니티에서 몇 가지 codemods를 작성했으며 저는 ember-codemod-v1-to-v2 ( ember-addon-migrator 도 옵션이지만 저는 그렇게 했습니다. 아직 테스트하지 않음).
npx [email protected] --addon-location="packages/addon" --test-app-location="packages/test-app"
- 애드온 패키지: 상위 앱에 제공될 것으로 예상되는 실제 애드온 코드입니다.
- v1 형식의 더미 앱과 동일한 역할을 수행하는 테스트 앱 패키지.
- 애드온 빌드(감시 모드 포함)
- 테스트 앱 서버 실행
- 테스트 앱에서 테스트 실행
번역 처리
translationsember-intl을 사용하면 프로젝트의 루트에 codemod에 의해 생략된 디렉토리가 있어 필요한 경우 번역이 누락됩니다 . translations이 문제를 해결하려면 디렉토리를 애드온의 패키지 루트로 이동한 다음 'files' 필드에 나열하여 packages/my-addon/package.json게시하고 상위 앱에서 사용할 수 있도록 해야 했습니다 .
{
"name": "my-addon",
"version": "0.0.13",
"keywords": [
"ember-addon"
],
...,
"files": [
"addon-main.cjs",
"dist",
"translations"
]
}
애드온은 Ember 데이터 어댑터와 함께 배송되기 때문에 상위 앱의 실행 환경에 따라 올바른 백엔드 호스트에 도달하도록 구성해야 합니다.
이전에는 다음과 같이 했습니다.
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;
}
}
불행히도 이것은 v2 형식이 마법과 빌드 시간 마법이 적기 때문에 더 이상 작동하지 않았습니다. 그러나 여전히 @embroider/macros. 이 패키지를 사용하여 개체 값을 업데이트하기만 하면 올바른 호스트를 구성할 수 있었습니다 config.
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'
}
}
}
});
}
공공재산 제공
실제로 애드온을 사용하는 앱에서 애드온을 연결한 후 일반적으로 애드온과 함께 제공되는 모든 이미지가 앱의 빌드에 없다는 것을 알았습니다.
애드온의 폴더에 있는 파일 public(그런데 로 이동해야 함 )은 다음 형식으로 packages/my-addon/public애드온 package.json의 메타 개체에 나열되어야 합니다.ember-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"
}
}
...
}
그러나 이것은 단지 몇 개의 공개 자산을 제공하는 애드온의 경우 매우 빠를 수 있지만 많은 자산이 있는 경우 감당할 수 없을 수 있으므로 빌트인 롤업 플러그인을 추가하기 위해 열린 풀 요청이ember-addon.public-assets 있습니다. 메타 개체를 디렉터리와 동기화 상태로 유지합니다 public.
CSS 다루기
이전에 언급했듯이 이 애드온은 Less CSS를 사용하여 사전 처리된 CSS와 함께 일부 구성 요소를 제공합니다. 또한 전에는 자신의 CSS를 가져오는 구성 요소가 없었지만 addon/styles/addon.less다른 관련 파일을 가져오는 진입점 파일이 있었습니다. 모든 구성 요소를 거치지 않고 CSS를 그 옆에 배치하기 위해 지금은 단일 CSS 파일을 계속 사용하기로 했습니다. 그래서 이 시점에서 처리해야 할 두 가지 문제가 있었습니다.
- JS 파일에서 가져오지 않은 CSS는 생략됩니다.
ember-cli-lessLess 파일을 처리하기 위해 더 이상 작동하지 않았습니다.
{
"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);
- 리팩토링의 경우: 모든 것이 서로 옆에 있습니다.
- 그것은 트리 쉐이킹을 더 쉽게 만들고 죽은 CSS를 브라우저에 전달하지 않습니다.
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
]
};
문제 해결
다음은 codemod를 실행한 후 쉽게 수정된 몇 가지 문제입니다.
- 선언 필드는 먼저 @babel/plugin-transform-typescript에 의해 변환되어야 합니다. 옵션을 활성화하여 수정됨
allowDeclareFields(https://babeljs.io/docs/babel-preset-typescript#allowdeclarefields) - 이전 가져오기(패키지 이름이 루트임)를 상대 가져오기로 교체하는 동안 codemod는 실수로 일부 구성 요소에서 동적으로 빌드된 자산 경로를 상대 가져오기로 교체하여 일부 이미지 경로를 손상시켰습니다. 여기에서 빠른 이중 확인이 필요할 수 있습니다.
- ember-auto-import가
css-loader상대 경로가 있는 URL을 처리하지 못했습니다. 이것은 이 마이그레이션 컨텍스트 외부에서도 발생했던 Webpack의 알려진 문제입니다. 지금은 (autoImport.cssLoaderOptions.urlcf.falsehttps://webpack.js.org/loaders/css-loader/#url) 문제를 해결합니다.

![연결된 목록이란 무엇입니까? [1 부]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































