오늘은 클라이언트 프로그램 개발이 다 끝나서, 배포를 위해 yarn dist
를 시도해봤습니다. 다음과 같은 에러가 발생합니다.
Uncaught Error: Cannot find module './main'
무엇이 잘못되었는지 확인하기 위해 electron-webpack-quick-start
로 새로운 프로젝트를 만들었습니다. 기존 코드를 새 프로젝트로 하나하나 옮기다 보니, 모듈을 dynamic import하는 index.js
부분에서 문제가 생기는 것을 확인했습니다. index.js
가 어떤 파일인지는 아래 게시글을 보시면 확인하실 수 있습니다.
2020/01/17 - [ElectronWebpack + React] - 이슈 6 단 한 줄! index.js로 내 코드 깔끔하게 import하기
2020/01/31 - [ElectronWebpack + React] - 이슈 11 React.createElement: type is invalid
제가 여러모로 잘못된 정보를 전파한 것 같네요...
개발할 때는 잘 돌아갔는데 같은 환경에서 배포용 어플리케이션을 돌리면 문제가 생깁니다. 그 이유는 바로,, 경로가 바뀌기 때문입니다. package.json
을 살펴보면 yarn dist
는 다음과 같은 명령어를 실행합니다.
// ...
"scripts": {
"dev": "electron-webpack dev",
"compile": "electron-webpack",
"dist": "yarn compile && electron-builder",
"dist:dir": "yarn dist --dir -c.compression=store -c.mac.identity=null"
},
// ...
바로 위에 yarn compile
은 electron-webpack
을 실행한다고 나와있으니 결국 yarn dist
는 npx electron-webpack && npx electron-builder
를 실행하는 것과 같은 효과를 가집니다.
electron-webpack
명령어를 실행하면 프로젝트 폴더 안에 dist
폴더가 생깁니다. 기본 설정을 건드리지 않았다면 구조는 다음과 같습니다. webpack을 통해 단일 파일로 형성됩니다.
webpack에서 사용하는 기본 config는 다음과 같습니다.
{
context: 'path/to/project/folder',
devtool: 'eval-source-map',
externals: [
'external',
'libraries'
],
node: { __dirname: true, __filename: true },
output: {
filename: '[name].js',
chunkFilename: '[name].bundle.js',
libraryTarget: 'commonjs2',
path: '/path/that/files/in/renderer/folder/are/saved'
},
target: 'electron-renderer',
resolve: {
alias: {
'@': '/path/to/renderer'
},
extensions: [ '.js', '.json', '.node', '.css' ]
},
// ...
}
개발 환경에서는 현재 디렉토리 경로를 가리키던 __dirname
변수가 배포 환경에서는 앱 내부 주소를 가리킵니다. (macOS 기준 /path/to/project/folder/dist/mac/test.app/Contents/Resources/app.asar
)
파일이 유동적으로 변하는 개발 환경에서는 기존 방식을 사용하고, 배포 환경에서는 하나하나 import 하기로 결정했습니다.
const glob = require('glob')
const path = require('path')
const isDevelopment = process.env.NODE_ENV !== 'production'
let files
module.exports = {}
if (isDevelopment) {
files = glob.sync(`./${__dirname}/!(index).js`)
}
else {
files = ['module1', 'module2']
}
for (const file of files) {
const m = require(`./${path.basename(file)}`)
for (const ele of Object.values(m)) {
module.exports[ele.name] = ele
}
}
와 해결! 난 천재다!! 이런 결과면 얼마나 좋겠습니까... 다시 yarn dist
를 진행한 후 켜보면 다음과 같이 나옵니다.
Error: Minified React error #130; visit https://reactjs.org/docs/error-decoder.html?invariant=130&args[]=undefined&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
at Error (webpack:/node_modules/react-dom/cjs/react-dom.production.min.js:273)
at ch (webpack:/node_modules/react-dom/cjs/react-dom.production.min.js:143)
at C (webpack:/node_modules/react-dom/cjs/react-dom.production.min.js:146)
at z (webpack:/node_modules/react-dom/cjs/react-dom.production.min.js:150)
at gh (webpack:/node_modules/react-dom/cjs/react-dom.production.min.js:172)
at R (webpack:/node_modules/react-dom/cjs/react-dom.production.min.js:263)
at gk (webpack:/node_modules/react-dom/cjs/react-dom.production.min.js:230)
at fk (webpack:/node_modules/react-dom/cjs/react-dom.production.min.js:229)
at Zj (webpack:/node_modules/react-dom/cjs/react-dom.production.min.js:223)
at Lj (webpack:/node_modules/react-dom/cjs/react-dom.production.min.js:214)
console에 찍어보면 undefined라고 나옵니다. 왜일까요? webpack 때문에 클래스 이름이 바뀌어서 그렇습니다.
아아.. 결국 일일이 찍어주는 수 밖에 없나 봅니다...
module.exports = {}
const isDevelopment = process.env.NODE_ENV !== 'production'
if (isDevelopment) {
const glob = require('glob')
const path = require('path')
const files = glob.sync(`./${__dirname}/!(index).js`)
for (const file of files) {
const m = require(`./${path.basename(file)}`)
for (const ele of Object.values(m)) {
module.exports[ele.name] = ele
}
}
}
else {
const makeModule = (name, module=[]) => ({
name: name,
module: module,
})
const files = [
makeModule("Info"),
makeModule("Seat"),
makeModule("Title"),
makeModule("SeatID"),
makeModule("Caution"),
makeModule("Feedback"),
makeModule("Password"),
makeModule("StudentID"),
makeModule("Navigation"),
makeModule("SelectSeat"),
]
for (const file of files) {
const m = require(`./${file.name.toLowerCase()}`)
module.exports[file.name] = m.default
for (const c of file.module) {
module.exports[c] = m[c]
}
}
}
-
덤
package.json
에 아래와 같은 코드를 추가하면 임포트 할 때import { module1 } from 'common'
과 같은 식으로 쓸 수 있다!!! 맨날 상대경로로만 사용했는데 절대경로로 추가할 수 있게 되어 기쁘다...// ... "electronWebpack": { "commonSourceDirectory": "src/components", } // ...
'React' 카테고리의 다른 글
이슈 13 electron react-router-dom (별로 특별할 것 없음), HashRouter BrowserRouter 차이 (0) | 2020.02.16 |
---|---|
이슈 12 react form 초기화하는 세 가지 방법 (0) | 2020.02.03 |
이슈 11 React.createElement: type is invalid (0) | 2020.01.31 |
이슈 10 react 다국어 지원, import { default as smt } from ... (0) | 2020.01.29 |
이슈 9 Parsing error: Unexpected token = eslint (0) | 2020.01.22 |