728x90
반응형

mp3 파일들을 연속으로 재생할 수 있는 웹페이지를 만들었다.

 

처음엔 단순하게 audio 태그를 이용하여 재생했다.

 

데스크톱에서 확인했을 때 잘 동작해서 문제가 없다고 생각했다.

 

그런데 모바일에서 확인해보니 처음 재생은 화면이 꺼져도 끝까지 잘 됐지만 다음 파일이 재생되지 않았다.

 

그래서 화면이 꺼지든가 브라우저가 백그라운드로 가도 재생이 되도록 해보려고 방법을 찾아봤다.

 

그러다가 PWA로 하면 원하는 기능이 되지 않을까 해서 찾아봤다.

 

찾아보니 PWA로 만든 음악 플레이어가 있어서 가능성이 보여 예제를 찾아 만들어 보기로 했다.

 

다음은 예제 코드를 참고하여 간단하게 PWA를 만든 코드 일부분이다.

 

manifest.json 파일을 만들어서 추가한다.

 

홈 화면에 추가했을 때 아이콘과 스플래시 화면이 나오도록 설정할 수 있다.

{
  "description": "Play mp3 files.",
  "display": "standalone",
  "icons": [
    {
      "src": "icon/icon-64.png",
      "sizes": "64x64",
      "type": "image/png"
    }
  ],
  "name": "PWA Test",
  "short_name": "PWA Test",
  "start_url": "/index.html",
  "background_color": "#3367D6",
  "theme_color": "#3367D6"
}

그리고 Service Worker를 등록하면 된다.

 

Service Worker는 브라우저가 백그라운드에서 실행하는 스크립트로 웹페이지와는 별개로 작동하며

 

웹페이지 또는 사용자 상호작용이 필요하지 않은 기능을 사용할 수 있게 해준다.

 

index.htmlService Worker를 등록하는 코드를 추가한다.

...
<head>
  <link rel="manifest" href="/manifest.json">
  <link rel="apple-touch-icon" sizes="180x180" href="/icons/icon-64.png">
</head>
<body>
  <script type="text/javascript">
    if('serviceWorker' in navigator) {
      navigator.serviceWorker
               .register('/pwa-examples/a2hs/sw.js')
               .then(function() { console.log('Service Worker Registered'); });
    }
  </script>
</body>
...

sw.js 파일에 다음 코드를 추가한다.

self.addEventListener('install', function(e) {
  e.waitUntil(
    caches.open('cache').then(function(cache) {
      return cache.addAll([
        '/',
        '/index.html',
        '/script.js',
        '/style.css',
        '/icon.png'
      ]);
    });
  );
});

self.addEventListener('fetch', function(e) {
  e.respondWith(
    caches.match(e.request).then(function(response) {
      return response || fetch(e.request);
    });
  );
});

iOS에서 사파리로 접속한 다음 _홈 화면에 추가_를 하면 설정한 아이콘 모양으로 홈 화면에 추가된다.

 

화면이 꺼지거나 앱을 종료해도 재생이 되는지 테스트했지만 재생이 되지 않았다.

 

하지만 안드로이드에서는 화면이 꺼지거나 앱을 꺼도 재생이 잘되는 것을 확인할 수 있었다.

 

참고 문헌

  1. https://github.com/mdn/pwa-examples

  2. https://developers.google.com/web/fundamentals/web-app-manifest

  3. https://developers.google.com/web/fundamentals/primers/service-workers?hl=ko

반응형
728x90
반응형

ejs를 2에서 3으로 업그레이드하고 나서 다음과 같은 에러가 발생했다.

SyntaxError: Unexpected identifier in index.ejs while compiling ejs

If the above error is not helpful, you may want to try EJS-Lint:
https://github.com/RyanZim/EJS-Lint
Or, if you meant to create an async function, pass `async: true` as an option.
    at new Function (<anonymous>)
    ...

에러 로그에서 어디에서 잘못됐는지 정확히 나오지도 않고

 

로그에서 나온 주소에서는 해결 방법을 찾을 수 없어 막막했다.

 

그래서 코드를 전부 제거하고 하나씩 찾아나가는 방법으로 어디가 문제인지를 찾았다.

 

원인은 include 하는 기존 방식이 제거돼서 에러가 발생했던 것이었다.

 

<% include ./header %>와 같이 돼있던 부분을 <%- include('header') %>와 같이 수정하면 된다.

 

참고 문헌

  1. https://github.com/mde/ejs/issues/476

반응형
728x90
반응형

Javascript에서 정규식을 사용하는 경우가 자주 있는데 그때마다 잊어버리는 게 있다.

 

반복해서 정규식을 이용해 문자열을 찾는 경우가 있는데

 

항상 2번째에서는 다음과 같이 값이 나오지 않는 경우가 발생했다

let re = /ab/g;
let str = 'abc'
re.exec(str)
   ==> ["ab"]
re.exec(str)
   ==> null

이유는 RegExp가 상태 저장(stateful)을 하기 때문이다.

 

이를 위해 RegExp.lastIndex로 마지막으로 찾은 위치를 저장하는데

 

위의 예시에서는 처음 수행하면 ab를 찾아서 값이 2가 된다.

 

다음에 수행될 때는 마지막으로 찾은 위치부터 수행하기 때문에

 

문자열을 찾지 못하고 lastIndex는 0으로 리셋된다.

 

그래서 반복해서 정규식으로 문자열을 찾으려면 정규식을 수행한 이후에

 

항상 lastIndex를 0으로 설정해야 원하는 결과를 얻을 수 있다.

re.lastIndex = 0;

 

참고 문헌

  1. https://stackoverflow.com/questions/11477415/why-does-javascripts-regex-exec-not-always-return-the-same-value

  2. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec

  3. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex

반응형

'JS' 카테고리의 다른 글

[JS] video.js 자동 재생이 안될 때 해결 방법  (0) 2020.09.24
[JS] Electron으로 앱만들기  (0) 2020.08.13
[JS] PWA 만들기  (0) 2020.02.20
[JS] ejs SyntaxError  (0) 2020.01.25
[JS] Grunt Webpack 버전별로 빌드하기  (0) 2020.01.25
728x90
반응형

Javascript 라이브러리를 만든 후 버전별로 빌드할 필요가 생겼다.

 

alpha/beta/release 이렇게 빌드를 하려고 했는데 생각처럼 되지 않아 시행착오를 여러 번 겪었다.

GruntWebpack을 사용하여 빌드하고 있는데

 

Webpackenv 파라미터에서 버전 정보를 받아서 빌드하도록 했다.

 

또한 버전별로 주소가 바뀌는 값이 있어 이를 동적으로 처리하기 위해 DefinePlugin을 이용했다.

 

Javascript에서 DefinePlugin에 정의된 키가 해당 값으로 자동으로 변경되어 빌드된다.

 

여기서 값을 설정할 때 중요한 것이 JSON.stringify로 값을 감싸줘야 제대로 동작한다.

 

webpack.config.js는 다음과 같이 작성하며 된다.

const webpack = require('webpack');
const path = require('path');
const config = require('./config.json');

module.exports = env => {
    if (!env || !env. VERSION) {
        env = {
            ...env,
            VERSION: 'release'
        };
    }
    const filename = env. VERSION === 'release' ? 'main.min.js' : `${env. VERSION}-main.min.js`;

    return {
        entry: './src/index.ts',
        target: 'node',
        mode: 'production',
        module: {
            rules: [
                ...
            ]
        },
        resolve: {
            extensions: [ '.ts', '.js' ]
        },
        plugins: [
            new webpack.DefinePlugin({
                SPECIFIC_URL: JSON.stringify(config.contexts[env.VERSION].SPECIFIC_URL)
            })
        ],
        output: {
            filename: filename,
            path: path.resolve(__dirname, 'dist')
        }
    };
};

다음과 같이 실행하면 된다.

$ webpack --env.VERSION=release

그리고 한번에 버전별로 빌드하기 위해 Grunt를 사용했다.

 

버전이 추가되도 자동으로 동작할 수 있도록 reduce를 이용했다.

 

다음과 같이 작성하여 사용하고 있다.

const path = require('path');
const webpackConfig = require('./webpack.config.js');
const versions = ['alpha', 'beta', 'release'];

module.exports = function(grunt) {
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        webpack: versions.reduce((obj, version) => {
            const app = version === 'release' ? 'app' : `${version}-app`;
            obj[app] = webpackConfig({VERSION: version});
            return obj;
        }, {})
    });

    grunt.loadNpmTasks('grunt-webpack');

    grunt.registerTask('default', ['webpack']);
};

 

참고 문헌

  1. https://webpack.js.org/guides/environment-variables/

  2. https://webpack.js.org/plugins/define-plugin/

반응형

'JS' 카테고리의 다른 글

[JS] video.js 자동 재생이 안될 때 해결 방법  (0) 2020.09.24
[JS] Electron으로 앱만들기  (0) 2020.08.13
[JS] PWA 만들기  (0) 2020.02.20
[JS] ejs SyntaxError  (0) 2020.01.25
[JS] RegExp 재사용할 때 문제 해결  (0) 2020.01.25

+ Recent posts