하나의 빌드 시스템 - 여러 Vue 앱 - 공유 구성 요소

이를 달성하는 방법과 그렇게 하는 동안 개발자 경험을 유지하는 방법.



2020년 9월 12일 최종 업데이트

Written with specific references to VueCli v3, but I think a good portion of whats contained within should be applicable across most FE codebases.



무엇과 이유



WelcomeQr에서 작업하는 동안 저는 사용자의 하위 도메인에서 게시된 콘텐츠를 제공하기 위한 별도의 앱을 만드는 것이 합리적이었습니다. 그래서 저는 프로젝트에 대한 현재 모노 리포지토리의 루트에 있는 VueCli를 사용하여 확장된 새 앱을 만드는 것으로 시작했습니다. subdoms 앱 이전에는 repo에 프론트엔드 애플리케이션과 끝점, 데이터베이스 및 정적 콘텐츠 제공을 위한 ExpressJs 서버가 포함되어 있었습니다(정적 콘텐츠는 Nginx 수준에서 더 빠르게 수행될 수 있었지만 그건 또 다른 이야기이며 현재에 만족합니다. 설정). 이제 두 개의 별도 프론트엔드 앱, 두 개의 빌드 시스템, 두 개의 린트 구성이 있으며 아직 코드 작성을 시작하지도 않았습니다. 새 앱을 작성하는 초기 단계에서 저는 기본 앱의 구성 요소를 사용하기 시작합니다. 이 단계에서는 구성 요소를 새 디렉터리에 복사하기만 하면 됩니다.

그래서, 그 이유이기도 합니다. 하나의 빌드 및 린트 설정을 사용하여 모든 프론트엔드 코드를 관리하고 싶었습니다.

완성의 길에서 내가 시도한 것들



나는 일반적으로 순진한 방식으로 일을 시작하며 결코 부정적인 것이 아닙니다. 새로운 것을 시도할 때 지점을 만들고 A에서 B로 직접 이동하는 것이 유용하고 효과적이라는 것을 알았습니다. 때로는 처음으로 작동하고 다른 때는별로 작동하지 않습니다. 이것은 후자였습니다.

내가 시도한 첫 번째 일은 단순히 repo의 루트에 공유 폴더를 만들고 모든 공유 코드를 이 폴더로 이동한 다음 공유된 모든 항목을 참조하는 두 앱의 경로를 변경하는 것입니다. 문제를 추측? 린트 또는 유형 검사가 없으며 내 sass 변수와 각 .vue 파일에 대한 보간도 이 시점에서 커스터드로 이동했습니다.

자, 문제 없습니다. tsconfig 파일을 프로젝트의 루트로 옮기겠습니다. 하지만 물론 일부 도구를 설치해야 하고 내 서버도 자체적으로 별도의 typescript 도구를 실행하고 있으며 이제 업스트림이 됩니다. 새로운 tsconfig에서. 이것이 빠른 해결이 될 수 없다는 것이 빠르게 명백해지고 있습니다. 점심 시간.

다음으로 시도한 것은 두 개의 별개vue.config.[app-name].js 파일과 Vue 환경 변수VUE_CLI_SERVICE_CONFIG_PATH를 사용하는 것이었습니다. 나는 this 게시물의 저자로부터 그것에 대한 몇 가지 참조를 찾았습니다. 누가 Vue 소스 코드에 묻힌 것을 발견했으며 문서화되지 않았지만 소스를 보니 합법적인 것처럼 보였습니다. 유명한 마지막 단어가 맞습니까?

나는 실제로 이것이 잠시 동안 승자가 될 것이라고 생각했지만 실제 경로에 의해 구석으로 물러 났고 각 앱에 대해 두 개의 매우 다른 index.html 파일이 필요했습니다. 여기에서 틀릴 수 있지만 내가 얻고있는 결과가 보였습니다. 물론 VueCli의 버그처럼, 내가 하고 있는 일이 문서에 없기 때문에 버그로 정의되지 않았을 것입니다. 오른쪽? ¯\_(ツ)_/¯
아래 코드는 vue.config.js 스크립트 섹션에서 가져온 package.json 파일을 분할하는 첫 번째 시도입니다.

  "scripts": {

    "serve:main": "env VUE_CLI_SERVICE_CONFIG_PATH=\"$PWD/vue.config.main.js\" vue-cli-service serve main-app/src/main.ts --dest main-app/dist",
    "build:main": "env VUE_CLI_SERVICE_CONFIG_PATH=\"$PWD/vue.config.main.js\" vue-cli-service build --dest main-app/dist main-app/src/main.ts",

    "serve:subdoms": "env VUE_CLI_SERVICE_CONFIG_PATH=\"$PWD/vue.config.subdoms.js\" vue-cli-service serve subdoms-app/src/main.ts",
    "build:subdoms": "env VUE_CLI_SERVICE_CONFIG_PATH=\"$PWD/vue.config.subdoms.js\" vue-cli-service build --dest subdoms-app/dist subdoms-app/src/main.ts"

  },

그리고 vue.config.main-app.js 파일.

const path = require('path')

module.exports = {
    chainWebpack: config => {

        // I've ommited stuff that isn't super relevant

        config.resolve.alias.set('@I', path.resolve(__dirname, '../interfaces'))
        config.resolve.alias.set('@shared', path.resolve(__dirname, './shared'))

    }
}

그것은 작동하지만 이상한 결과를 낳았고 문서화 된 작업 방식에 더 가까운 더 나은 솔루션을 찾은 것 같습니다.

해결책



서두에 죄송합니다. 여기에 양고기 소스가 있습니다.
vue.config.js
const path = require('path')

const isMainApp = process.env.APP_TYPE === 'main-app'
const appDir = isMainApp ? 'main-app' : 'subdoms-app'

module.exports = {
    outputDir: path.resolve(__dirname, `${appDir}/dist`),
    chainWebpack: config => {

        // I've ommited all the non-relevant config stuff

        config.resolve.alias.set('@I', path.resolve(__dirname, '../interfaces'))
        config.resolve.alias.set('@shared', path.resolve(__dirname, './shared'))

        config.plugin("html").tap(args => {
            args[0].template = path.resolve(__dirname, `${appDir}/index.html`)
            return args
        })

    },
    devServer: {
        port: isMainApp ? 8080 : 7070
    },
}
package.json
{
  "name": "example config",
  "version": "0.1.0",
  "scripts": {

    "serve:main": "env APP_TYPE=\"main-app\" vue-cli-service serve main-app/src/main.ts",
    "build:main": "env APP_TYPE=\"main-app\" vue-cli-service build main-app/src/main.ts",

    "serve:subdoms": "env APP_TYPE=\"subdoms-app\" vue-cli-service serve subdoms-app/src/main.ts",
    "build:subdoms": "env APP_TYPE=\"subdoms-app\" vue-cli-service build subdoms-app/src/main.ts"

  },
  "dependencies": {
      // deps...
  }
}
folder structure
/
    .git
    .gitignore
    rundev.sh
    deploy.sh
    /front
        /main-app
            /dist
            /src
            index.html
        /subdoms-app
            /dist
            /src
            index.html
        /public
            /images
                logo.png
                ...
            /icons
                check.svg
                ...
        /shared
            /components
                component.vue
                ...
            /api
                auth.ts
                api.ts
            /utils
                seo.ts
        jsconfig.ts
        eslint.js
        package.json
        vue.config.js
    /server
        ...
    /scripts
        bleh.sh
        ....

결과



하나의 빌드 시스템, 하나의 tsconfig 및 linting 설정, 공유 코드 및 원하는 만큼의 앱 모두 동시에 실행할 수 있으며 자체sass 빌드가 있습니다. 꽤 깔끔하죠? 나는 이것이 더 큰 코드베이스에서 멋진 효과에 사용될 수 있다고 생각합니다.

단점



Onepackage.json , 이것이 번들 크기에 영향을 미치지는 않지만 가져온 웹팩의 번들 때문에 시간이 지남에 따라 노이즈가 생길 수 있다고 주장할 수 있습니다. 저에게는 받아들일 수 있는 문제입니다.

Hope you enjoyed reading and found some of this useful.

좋은 웹페이지 즐겨찾기