I have a Vue.js app which i'm currently using workbox to cache so it works offline. However, videos don't seem to work in Safari.
I've researched and all signs point to this:
https://developers.google.com/web/tools/workbox/guides/advanced-recipes#cached-av
but it doesn't seem to work for me.
Here's my code as it stands:
Webpack
configureWebpack: {
plugins: [
new InjectManifest({
swSrc: './src/sw.js',
swDest: "sw.js",
maximumFileSizeToCacheInBytes: 5000000000
})
]}
sw.js (service worker)
import { skipWaiting, clientsClaim } from "workbox-core";
import { precacheAndRoute } from "workbox-precaching";
import { registerRoute } from "workbox-routing";
import { CacheFirst } from "workbox-strategies";
import { CacheableResponsePlugin } from "workbox-cacheable-response";
import { RangeRequestsPlugin } from "workbox-range-requests";
registerRoute(
({ url }) => url.pathname.endsWith(".mp4"),
new CacheFirst({
plugins: [
new CacheableResponsePlugin({ statuses: [200] }),
new RangeRequestsPlugin()
]
})
);
skipWaiting();
clientsClaim();
precacheAndRoute(self.__WB_MANIFEST);
This is likely because your .mp4 files have a __WB_MANIFEST URL query parameter appended to them in the cache, since they need to be versioned by Workbox's precaching logic.
A quick solution would be to set matchOptions when constructing the strategy:
new CacheFirst({
matchOptions: { ignoreSearch: true },
plugins: [
new CacheableResponsePlugin({ statuses: [200] }),
new RangeRequestsPlugin()
]
})
I realised as I was precaching I had to specify what cache to use in the CacheFirst object, as the default is set to the runtime cache. To do this, I imported cacheNames from workbox-core
import { skipWaiting, clientsClaim, cacheNames } from "workbox-core";
Then I set the precache name
const precacheCacheName = cacheNames.precache;
Then in when setting up the CacheFirst object I specified the name as such:
new CacheFirst({
cacheName: precacheCacheName,
Here's the complete code:
import { skipWaiting, clientsClaim, cacheNames } from "workbox-core";
import { precacheAndRoute } from "workbox-precaching";
import { registerRoute } from "workbox-routing";
import { CacheFirst } from "workbox-strategies";
import { CacheableResponsePlugin } from "workbox-cacheable-response";
import { RangeRequestsPlugin } from "workbox-range-requests";
const precacheCacheName = cacheNames.precache;
registerRoute(
({ url }) => url.pathname.endsWith(".mp4"),
new CacheFirst({
cacheName: precacheCacheName,
matchOptions: { ignoreSearch: true },
plugins: [
new CacheableResponsePlugin({ statuses: [200] }),
new RangeRequestsPlugin()
]
})
);
skipWaiting();
clientsClaim();
precacheAndRoute(self.__WB_MANIFEST);
Related
I am building a custom Nuxt3 module and want to use tailwindcss to style
my components.
However, I am having trouble setting up tailwindcss for my module.
I tried to set it up, like I would with a normal css file:
In the 'src/' folder I have the follwing components:
'runtime/css/tailwind.css':
#import "tailwindcss/base";
#import "tailwindcss/components";
#import "tailwindcss/utilities";
'runtime/tailwind.config.js':
import defaultTheme from ("tailwindcss/defaultTheme")
module.exports = {
content: {
files: [
"./components/**/*.{vue,js}",
"./layouts/**/*.vue",
"./pages/**/*.vue",
"./plugins/**/*.{js,ts}",
"./modules/**/*.{js,ts,vue}"
],
},
theme: {
extend: {
fontFamily: {
sans: ['"Inter var"', ...defaultTheme.fontFamily.sans],
},
},
},
variants: {
extend: {},
}
};
'module.ts':
import { resolve } from 'path'
import { fileURLToPath } from 'url'
import { defineNuxtModule, addPlugin, addComponent } from '#nuxt/kit'
export interface ModuleOptions {
css: boolean
}
export default defineNuxtModule<ModuleOptions>({
meta: {
name: '#nuxt-module/polkadotjs-wallet',
configKey: 'polkadotjs-wallet'
},
defaults: {
css: true,
},
setup (options, nuxt) {
const runtimeDir = fileURLToPath(new URL('./runtime', import.meta.url))
nuxt.options.build.transpile.push(runtimeDir)
// add the plugin
addPlugin(resolve(runtimeDir, 'plugin'))
// add components
const componentsDir = resolve(runtimeDir, "components")
addComponent({
name: "Hello",
filePath: resolve(componentsDir, "Hello.vue")
})
if(options.css) {
nuxt.options.css.push(resolve(runtimeDir, "css/tailwind.css"))
}
}
})
While this approach works to use normal css styling, I cannot make tailwind work like that.
Running it like this does not give me an error, but it also does not enable me to use tailwind.
I think I find a way, but I'm just discovering Nuxt 3.
Maybe my answer won't be perfect, but as far as I read the documentation and the #nuxtjs/tailwindcss code, that's all I found to work.
move your runtime/css/tailwind.css to runtime/tailwind.css
I'm not sure this file is really useful, as there is a default one provided by #nuxtjs/tailwindcss (see in your node_modules/#nuxtjs/tailwindcss/dist/runtime/tailwind.css)
update your tailwind.config.js for content property. It's an array of string for me. Actually, your paths are relatives. But in your app, these paths will take the components app and not the one of your module. You need to give absolute paths.
import defaultTheme from ("tailwindcss/defaultTheme")
import { fileURLToPath } from 'node:url'
const srcDir = fileURLToPath(new URL('../', import.meta.url))
/** #type {import('tailwindcss').Config} */
export default {
content: [
srcDir + '/**/*.{js,ts,vue}', // or separate in folders ?
],
theme: {
extend: {
fontFamily: {
sans: ['"Inter var"', ...defaultTheme.fontFamily.sans],
},
},
},
variants: {
extend: {},
}
};
last part, but the most important, you need to update your module.ts. I would write yours like this :
async setup (options, nuxt) {
const runtimeDir = fileURLToPath(new URL('../src/runtime', import.meta.url))
/**
* Here, you use the installModule to specify that
* your module USE the #nuxtjs/tailwindcss module.
* I think this is the way to add the tailwind module
* to your playground, or the app that will use your module
*/
await installModule('#nuxtjs/tailwindcss', {
/**
* Here, you specify where your config is.
* By default, the module have a configPath relative
* to the current path, ie the playground !
* (or the app using your module)
*/
configPath: resolve(runtimeDir, 'tailwind.config'),
})
// add components
const componentsDir = resolve(runtimeDir, "components")
addComponent({
name: "Hello",
filePath: resolve(componentsDir, "Hello.vue")
})
/**
* for these lines, I don't know if they are still useful
* please check them before keeping them :-)
*/
const runtimeDir = fileURLToPath(new URL('./runtime', import.meta.url))
nuxt.options.build.transpile.push(runtimeDir)
// add the plugin
addPlugin(resolve(runtimeDir, 'plugin'))
if(options.css) {
nuxt.options.css.push(resolve(runtimeDir, "css/tailwind.css"))
}
}
Does this help you ?
References :
installModule for Nuxt3 Modules
default configPath for #nuxtjs/tailwindcss
I have one js file which needs to be put in the public directory and needs to add it in the final production build as a text/javascript.
I have checked the options in vite config but couldn't find anything useful. The files I add contain a global JSON object and can be accessed directly.
To achieve this, I tried this solution.
vite.config.ts
import { fileURLToPath, URL } from "url";
import path from 'path';
// import test from "./src/assets/test.js"
import test from "./public/test.js"
import { defineConfig , loadEnv} from "vite";
import vue from "#vitejs/plugin-vue";
import { loadingScript } from 'vite-plugin-loading-script'
export default defineConfig(({ command, mode }) => {
// Load env file based on `mode` in the current working directory.
// Set the third parameter to '' to load all env regardless of the `VITE_` prefix.
const env = loadEnv(mode, process.cwd(), '')
return {
// vite config
define: {
__APP_ENV__: JSON.stringify(env.VITE_REDIRECT_URL),
__TEST__: test,
},
plugins: [vue()],
server: {
hmr: {
overlay: false,
},
},
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
},
},
build: {
// rollupOptions: {
// external: ['__APP_ENV__'],
// output: {
// globals: {
// __APP_ENV__: JSON.stringify(env.VITE_REDIRECT_URL),
// }
// }
// }
}
}
});
test.js
export default {
REDIRECT_URL: "https://example.com/",
API_URL: "https://example.com/",
};
with the above changes, I got the console.log('__TEST__', __TEST__) as expected JSON object but it doesn't work with the production build.
maybe you can try including the js file to the html in the public directory
I added sentry monitoring to my quasar app but sentry does not receive any errors and does not show up in its panel
i created /src/boot/sentry.js and write this codes:
import { boot } from "quasar/wrappers";
import * as Sentry from "#sentry/vue";
import { BrowserTracing } from "#sentry/tracing";
export default boot(({ app, router }) => {
Sentry.init({
app,
dsn: "<my sentry dns>",
integrations: [
new BrowserTracing({
routingInstrumentation: Sentry.vueRouterInstrumentation(router),
tracingOrigins: ["localhost", "my-site-url.com", regex],
}),
],
trackComponents: true,
tracesSampleRate: 1.0,
});
});
My Quasar app is ssr. How should i fix it?
I solved my problem by changing the code as shown below:
import { boot } from "quasar/wrappers";
import * as Sentry from "#sentry/browser";
import * as Integrations from "#sentry/integrations";
export default boot(({ Vue }) => {
Sentry.init({
dsn: "<dns comes here>",
release: process.env.SENTRY_RELEASE,
integrations: [
new Integrations.Vue({ Vue, attachProps: true }),
new Integrations.RewriteFrames({
iteratee(frame) {
// Strip out the query part (which contains `?__WB_REVISION__=**`)
frame.abs_path = frame.abs_path.split("?")[0];
return frame;
},
}),
],
});
});
I am trying to use vite in one of my existing project. After long hard work I finally managed to make everything work in development mode. But, when I tried to test the app after building scripts with vite build, all dynamic imports failed for me. The issue was, all the import statements were being converted to __import__. If I manually replace __import__ with import on built bundles, then everything works. I tried removing #vitejs/plugin-legacy but, it still did not work.
Here is my vite.config.ts file
import { UserConfigFn } from 'vite';
import RubyPlugin from 'vite-plugin-ruby';
import FullReload from 'vite-plugin-full-reload';
import styleLint from '#amatlash/vite-plugin-stylelint';
import eslintPlugin from 'vite-plugin-eslint';
import legacy from '#vitejs/plugin-legacy';
import { resolve as _resolve, join } from 'path';
import * as tsconfig from './tsconfig.json';
const paths = tsconfig.compilerOptions.paths;
const defaultAlias = Object.keys(paths).reduce((acc, key) => {
// eslint-disable-next-line #typescript-eslint/ban-ts-comment
// #ts-ignore
const value = paths[key][0];
const path: string = key.replace('/*', '/');
acc.push({
find: path,
replacement: _resolve(__dirname, value.replace('/*', '/').replace('.//', './')) + '/',
});
return acc;
}, [] as any[]);
const configFn: UserConfigFn = ({ mode, command }) => {
const plugins =
mode === 'development' && command === 'serve'
? [
styleLint({
exclude: ['node_modules', 'public', 'plyr.css'],
}),
eslintPlugin({
fix: true,
exclude: ['node_modules', '**/legacy.js'],
}),
FullReload(['config/routes.rb', 'app/views/**/*']),
]
: [];
return {
plugins: [...plugins, legacy({}), RubyPlugin()],
css: {
postcss: '',
},
resolve: {
alias: [
...defaultAlias,
{
find: /~(.+)/,
replacement: join(process.cwd(), 'node_modules/$1'),
},
],
},
build: {
sourcemap: process.env.RAILS_ENV !== 'production',
polyfillDynamicImport: true,
rollupOptions: {
output: {
manualChunks: (id) => {
if (id.includes('node_modules')) {
if (id.includes('jquery')) {
return 'jquery';
}
if (
/creditcards|snabbdom-form|email-validator|format-numbe|form-serialize|phone-regex|email-regex|currency-regex|format-number|snake-case|number-format|superagent/.test(
id
)
) {
return 'formHelpers';
}
if (id.includes('chart.js')) {
return 'chartJs';
}
if (id.includes('moment')) {
return 'momentJs';
}
if (id.includes('imagesloaded')) {
return 'imagesLoaded';
}
if (id.includes('uuid')) {
return 'uuid';
}
if (id.includes('flimflam')) {
return 'flimflam';
}
if (/cropperjs|guillotine/.test(id)) {
return 'imageHelpers';
}
if (/ff-dashboard|ff-file-uploader/.test(id)) {
return 'ffDashboard';
}
return 'vendor';
}
},
},
},
},
clearScreen: false,
};
};
export default configFn;
Turns out it was because polyfillDynamicImport to true.
I am trying to make Jasmine & Karma framework into the current angular application running in ver 8.2. But i am coming across this weird error inside the Karma test running window:
Failed: Unexpected value 'DecoratorFactory' imported by the module 'DynamicTestModule'. Please add a #NgModule annotation.
What is the problem?
My componenent.spec.ts looks like this:
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { HomeComponent } from './home.component';
import { NO_ERRORS_SCHEMA} from '#angular/core';
import {RouterTestingModule} from '#angular/router/testing';
import {HttpClientTestingModule} from '#angular/common/http/testing';
import { MsalService } from '#azure/msal-angular';
import { Store } from '#ngrx/store';
import { Pipe } from '#angular/core';
describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule, HttpClientTestingModule, Pipe]
,declarations: [HomeComponent]
,schemas:[NO_ERRORS_SCHEMA]
,providers: [
{provide: MsalService, useFactory: '' },
{provide: Store, useFactory: '' }
]
})
.compileComponents();
}));
it('should have header text', async(() => {
const fixture = TestBed.createComponent(HomeComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
//expect(compiled.querySelector('.header-txt').textContent).toContain('Tax');
}));
});
I found the cause :-
export class MockStore<T> {
private state: BehaviorSubject<T> = new BehaviorSubject(undefined);
setState(data: T) { this.state.next(data); }
select(selector?: any): Observable<T> {
return this.state.asObservable();
}
pipe() {}
dispatch(action: any) { }
}
========================================================================
TestBed.configureTestingModule({
{provide: Store, useFactory: 'MockStore' }
..............
The useFactory property must be some custom class name. Now i mocked the store class.