3

I want to create a service worker.

DISCLAMER: I don't wanna use serviceworker-webpack-plugin, it adds a lot of overhead that I simply don't need. I'm 100% sure that webpack is able to serve transpiled js/ts files as static files.

So I have main.ts and sw.ts:

  • main.ts should be transpiled via ts-loader and injected into index.html, when I run webpack-dev-server main.ts should support autoreload , as dev-server does by default.
  • sw.ts on the other hand should be transpiled via ts-loader as well and it SHOUDN'T be injected into index.html. Also if I run webpack-dev-server, the dev-server shouldn't add hotreload js code there. I just want sw.js to be transplied.
  • Also I would like to have a reference to sw.js during runtime from main.js. File-loader should provide it the same way as it does it for .css files.

Attemp #1

My first attemp was to create 2 entries in webpack config like below:

entry: {'main': './src/main.ts', 'sw':'./src/sw.ts'},

To prevent sw.ts from injecting I could use index.ejs and manually check js filename for if. This scenario works but while being on dev-server, webpack-dev-server adds hotreload code and sw.js fails at runtime within window not defined, which is logical, since service workers don't have window object.

Attemp #2, link to github

But then I tried file-loader, which looks like below:

webpack.config.js:

const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: ['./src/main.ts'],
  plugins: [
    new HtmlWebpackPlugin({hash: true, template: 'src/index.html'}),
  ],
  devtool: '#source-map',
  module: {
    rules: [
      {
        test: /sw\.ts$/,
        exclude: /node_modules/,
        loader: 'file-loader',
        options: {
          outputPath: '',
          name: 'sw.js?[sha512:hash:base64:6]',
        }
      },
      {
        test: /\.ts$/,
        loader: 'ts-loader',
      },
    ],
  },
};

tsconfig.json:

{
  "compilerOptions": {
    "lib": ["es2017", "dom"],
    "module": "es2015",
    "moduleResolution": "node",
    "target": "es5",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true
  },
  "exclude": [
    "./node_modules"
  ]
}

main.ts;

import './sw.ts'
console.log('main.ts');

sw.ts:

import {LoggerFactory, LogStrict} from 'lines-logger';
console.log('sw file');
let loggerFactory: LoggerFactory = new LoggerFactory(LogStrict.LOG_WITH_WARNINGS);

Output sw.js:

import { LoggerFactory, LogStrict } from 'lines-logger';
console.log('sw file');
var loggerFactory = new LoggerFactory(LogStrict.LOG_WITH_WARNINGS);

Why webpack doesn't resolve module dependencies? Is there another approach to handle service worker?

deathangel908
  • 8,601
  • 8
  • 47
  • 81

1 Answers1

-1

My advice (you're not going to like it) is that service workers have some complexity involved. I recommend using a project like WorkBox to make your life easier:

https://developers.google.com/web/tools/workbox/guides/generate-service-worker/webpack

I've blogged about this in the past in case it helps: https://blog.johnnyreilly.com/2017/11/the-typescript-webpack-pwa.html

Apologies, I know this isn't exactly what you're looking for. (Related issue on ts-loader: https://github.com/TypeStrong/ts-loader/issues/804 )

John Reilly
  • 5,791
  • 5
  • 38
  • 63