웹 assembly 는 전단 프로젝트 (하) - 웹 팩 과 웹 assembly 에 적 용 됩 니 다.

이전 글 에서 WebAssembly 는 전단 프로젝트 (상) - webassembly 모듈 의 작성 에 사용 되 었 습 니 다. @ nefe / gis 모듈 의 작성 과 발표.그러나 웹 assembly 는 현재 웹 팩 4 를 주요 컴 파일 도구 로 하 는 실제 프로젝트 응용 에 여전히 문제 가 존재 합 니 다.
웹 팩 4 에 wasm 파일 에 대한 컴 파일 지원 이 추가 되 었 음 에 도 불구 하고 wasm 모듈 을 작성 한 후 웹 팩 과 결합 하 는 과정 에서 wasm 모듈 을 올 바 르 게 불 러 올 수 없습니다.네 @ nefe / gis 컴 파일 출력 파일 검사 후 새로운 솔 루 션 wasm - module - webpack - plugin 이 생 겼 습 니 다.
발생 한 문제
전단 공사 에 직접 도입 @ nefe / gis 를 사용 하면 콘 솔 에서 오류 정 보 를 출력 합 니 다.
index.js?558c:1 GET http://localhost:8080/gps.wasm 404 (Not Found)
Uncaught (in promise) TypeError: Incorrect response MIME type. Expected 'application/wasm'.
인 용 된 @ ne 보기fe / gis / dist / index. js 에서 발견 한 말
var Pn="undefined"!=typeof location?location.pathname.split("/"):[];Pn.pop(),(Cn?WebAssembly.instantiateStreaming(fetch(Pn.join("/")+"/gps.wasm"),o):fetch(Pn.join("/")+"/gps.wasm").then(e=>e.arrayBuffer()).then(e=>WebAssembly.instantiate(e,o)))

오류 가 발생 했 을 때 fetch 가 루트 에서 wasm 파일 을 직접 가 져 왔 지만 파일 이 생 성 되 거나 이동 되 지 않 았 습 니 다. webpack 은 fetch 가 불 러 온 파일 을 처리 하지 못 해 wasm 로 딩 에 실 패 했 습 니 다.
babel
웹 팩 은 js 의 fetch 문 구 를 처리 하지 못 해 위의 문제 가 발생 했 습 니 다. 그러면 fetch 문 구 를 처리 할 수 있 는 방법 은 한 가지 밖 에 없습니다. 그것 이 바로 babel 입 니 다.다음은 babel 플러그 인 처리 fetch 로 wasm 을 불 러 오 는 상황 을 작성 합 니 다.
// babel-plugin.js
module.exports = function() {
  return {
    visitor: {
      CallExpression(path, state) {
        if(path.node.callee.name === 'fetch'){
          const argument = JSON.parse(JSON.stringify(path.node.arguments[0]));
          for (const i in argument.right) {
            if (i === 'value' && argument.right[i].endsWith('.wasm')) {
             console.log('argument.right[ i ]', argument.right[ i ], 'state.file.opts.filename', state.file.opts.filename);
            }
          }
        }
      },
    }
  }
};

웹 팩 에서 사용
// webpack.config.js
const path = require('path');
const BabelPlugin = require('./babel-plugin');
module.exports = {
  module: {
    rules: [
      ...
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [ path.join(process.cwd(), './node_modules/@ne_fe/gis') ],
        options: {
          plugins: [ BabelPlugin ],
        },
      },
      ...
    ],
  },
  plugins: [
    ...
  ],
};

웹 팩 을 시작 하여 컴 파일, 콘 솔 출력
argument.right[ i ] /gps.wasm 
state.file.opts.filename C:\dir\test
ode_modules\@ne_fe\gis\dist\index.js

최종 적 으로 fetch 가 불 러 온 wasm 파일 이름과 fetch 구문 이 있 는 파일 을 얻 었 습 니 다.
webpack
이전 단계 에서 fetch 문 구 를 불 러 온 wasm 파일 이름과 fetch 문 구 를 가 져 왔 습 니 다.wasm 파일 을 웹 팩 컴 파일 결과 에 출력 하기 위해 서 는 웹 팩 플러그 인 을 추가 해 야 합 니 다.수정 후, 전체 wasm 과 webpack 을 결합 한 플러그 인 은 다음 과 같 습 니 다.
// event-listener.js
const EventEmitter = require('events').EventEmitter;
class Events extends EventEmitter {
  constructor(prop) {
    super(prop);
    this.data = {};
  }
}
const events = new Events();
events.on('wasm', data => {
  if (!events.data[data.wasmRefFileName]) {
    events.data[data.wasmRefFileName] = {};
    events.data[data.wasmRefFileName][data.wasmRefPath] = data.wasmDir;
  } else {
    if (!events.data[data.wasmRefFileName][data.wasmRefPath]) {
      events.data[data.wasmRefFileName][data.wasmRefPath] = data.wasmDir;
    }
  }
});
module.exports = events;
// babel-plugin.js
const eventEmitter = require('./event-listener');
const pathInternal = require('path');
module.exports = function() {
  return {
    visitor: {
      CallExpression(path, state) {
        if(path.node.callee.name === 'fetch'){
          const argument = JSON.parse(JSON.stringify(path.node.arguments[0]));
          for (const i in argument.right) {
            if (i === 'value' && argument.right[i].endsWith('.wasm')) {
              eventEmitter.emit('wasm', {
                wasmRefPath: argument.right[i],
                wasmRefFileName: state.file.opts.filename,
                wasmDir: pathInternal.parse(state.file.opts.filename).dir,
              });
            }
          }
        }
      },
    }
  }
};
// webpack-plugin
const eventEmitter = require('./event-listener');
const path = require('path');

class WasmPlugin {
  apply(compiler) {
    compiler.plugin('emit', function(compilation, callback) {
      for (const i in eventEmitter.data) {
        for (const j in eventEmitter.data[i]) {
          const filePath = path.join(eventEmitter.data[ i ][ j ], '.' + j);
          const content = compiler.inputFileSystem._readFileSync(filePath);
          const stat = compiler.inputFileSystem._statSync(filePath);
          const wasmRefPath = j;
          const wasmName = wasmRefPath.substring(1, wasmRefPath.length);
          compilation.assets[wasmName] = {
            size() {
              return stat.size;
            },
            source() {
              return content;
            },
          };
        }
      }
      callback();
    });
  }
}

module.exports = WasmPlugin;

이벤트 - listener 의 역할 은 babel - plugin 에서 얻 은 wasm 관련 정 보 를 저장 하고 webpack 플러그 인 이 실 행 될 때 사용 하 는 것 입 니 다. webpack - plugin 은 가 져 온 wasm 파일 을 올 바른 경로 로 출력 합 니 다.
관련 된 기술 은 주로 comonjs 모듈 메커니즘, babel 플러그 인 작성 과 webpack 플러그 인 작성 입 니 다.
쓰다
wasm - module - webpack - plugin 또는 @ ne 참조 가능fe / gis, start 를 환영 합 니 다.
뒷말
비록 webassembly 의 등장 은 전단 개발 고성능 브 라 우 저 응용 에 중대 한 역할 을 했 음 에 도 불구 하고 webpack 4 는 webassembly 에 대한 지원 을 추 가 했 지만 현재 webpack 컴 파일 을 위주 로 하 는 전단 공정 이 webassembly 에 대한 지원 은 여전히 우호 적 이지 않 고 개발 난이도 가 적지 않 으 므 로 앞으로 더 좋 은 해결 방안 이 있 기 를 바 랍 니 다.  웹 어 셈 블 리 전단 프로젝트 (상) - 웹 어 셈 블 리 모듈 의 작성

좋은 웹페이지 즐겨찾기