I am developing a project with nuxt. I installed Service Worker to this project using this package. The nuxt.config.js file is like this:
export default {
mode: 'universal',
/*
** Headers of the page
*/
head: {
title: 'my_project',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1'},
{ hid: 'description', name: 'description', content: pkg.description }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
/*
** Customize the progress-bar color
*/
loading: { color: '#fff' },
/*
** Global CSS
*/
css: [
'~/static/css/base.css',
'~/static/css/hooper.css',
'~/static/css/font-awesome/css/all.min.css',
],
/*
** Plugins to load before mounting the App
*/
plugins: [
{ src: '~plugins/ga.js', ssr: false }
],
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://axios.nuxtjs.org/usage
'#nuxtjs/axios',
// Doc: https://bootstrap-vue.js.org/docs/
'bootstrap-vue/nuxt',
'#nuxtjs/pwa',
'#nuxtjs/device',
],
manifest:{
"short_name": "my_project",
"name": "my_project",
"icons": [
{
"src": "/static/icon.png",
"type": "image/png",
},
],
"start_url": "/",
"background_color": "white",
"display": "standalone",
"scope": "/",
"theme_color": "white"
},
workbox:{
},
/*
** Axios module configuration
*/
axios: {
// See https://github.com/nuxt-community/axios-module#options
},
/*
** Build configuration
*/
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {
}
},
hooks:{
// This hook is called before generatic static html files for SPA mode
'generate:page': (page) => {
if(page.path.includes('/amp/')){
page.html = modify_html(page.html)
}
},
// This hook is called before rendering the html to the browser
'render:route': (url, page, { req, res }) => {
if(url.includes('/amp/')){
page.html = modify_html(page.html)
}
}
}
}
But Service Worker is so slow. for example:
In this example normal query to the server takes 1.43 seconds and Service Worker query takes 1.37 seconds. How can i make Service Worker faster?
Related
I have a nextjs project with a :client param which represents a client, like this:
domain.com/:client
And I have multiple clients... so I need to do this rewrite:
:client.domain.com -> domain.com/:client
For example for clients:
google.domain.com -> domain.com/google
netflix.domain.com -> domain.com/netflix
...
Inside the same project.
Any way to do that?
You can use the redirects option in the vercel.json, as Maxime mentioned.
However, it requires 1 extra key.
For example, if your app is available at company.com:
{
...
redirects: [
{
"source": "/",
"has": [
{
"type": "host",
"value": "app.company.com"
}
],
"destination": "/app"
}
]
}
More info:
Example Guide
vercel.json docs
Create a config in your project root with next.config.js
If this file exists add the following snippet to it, Mind you, we used example.com in place of domain .com as Body cannot contain "http://domain. com" in stackoverflow
// next.config.js
module.exports = {
async redirects() {
return [
{
source: "/:path*",
has: [
{
type: "host",
value: "client.example.com",
},
],
destination: "http://example.com/client/:path*",
permanent: false,
},
];
},
};
To confirm it's also working in development, try with localhost
module.exports = {
reactStrictMode: true,
// async rewrites() {
async redirects() {
return [
{
source: "/:path*",
has: [
{
type: "host",
value: "client.localhost",
},
],
destination: "http://localhost:3000/client/:path*",
permanent: false,
},
];
},
};
Dynamic Redirect
To make it dynamic, we'll create an array of subdomains
const subdomains = ["google", "netflix"];
module.exports = {
async redirects() {
return [
...subdomains.map((subdomain) => ({
source: "/:path*",
has: [
{
type: "host",
value: `${subdomain}.example.com`,
},
],
destination: `https://example.com/${subdomain}/:path*`,
permanent: false,
})),
];
},
}
You can read more from the official next.js doc redirects or rewrite
No such file or directory, when using Vite and Antd Pro Layout
This is file vite.config.ts:
import { defineConfig } from 'vite';
import reactRefresh from '#vitejs/plugin-react-refresh';
import path from 'path';
import vitePluginImp from 'vite-plugin-imp';
export default defineConfig({
plugins: [
reactRefresh(),
vitePluginImp({
libList: [
{
libName: 'antd',
style: (name) => {
return `antd/lib/${name}/style/index.less`;
},
},
],
}),
],
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true,
modifyVars: {
...{
'primary-color': '#1DA57A',
'link-color': '#1DA57A',
'border-radius-base': '2px',
},
},
},
},
},
resolve: {
alias: [
{
find: /^~/,
replacement: path.resolve(__dirname, 'src'),
},
],
},
optimizeDeps: {
include: ['#ant-design/icons'],
},
});
This is my config to using antd, antd-pro-layout with vite.
But I received the error:
[vite] Internal server error: ENOENT: no such file or directory, open
'/Users/tranthaison/DEV/vite2-react-ts/srcantd/es/style/themes/default.less'
Can someone help me to fix it?
I had some problems when using React + Antd in Vite.
Thanks for #theprimone for the answer. But the answer is incomplete. I will complete the answer here.
First time, add additional config to Less Preprocessor:
Add this config to your vite.config.js file:
{
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true,
},
},
},
}
Second, setting module aliases to fix Less #import problem:
Again, add the following config into your vite.config.js file:
{
resolve: {
alias: [
{ find: /^~/, replacement: "" },
],
},
}
Last, install vite-plugin-imp plugin to solve Antd ES problem:
Install the vite-plugin-imp dependencies:
pnpm add -D vite-plugin-imp
# or
npm i -D vite-plugin-imp
then, setup the plugin in your vite.config.js file:
{
plugins: [
// React plugin here
vitePluginImp({
libList: [
{
libName: "antd",
style: (name) => `antd/es/${name}/style`,
},
],
}),
];
}
The final configuration in vite.config.js file will look like this:
import { defineConfig } from "vite";
import reactRefresh from '#vitejs/plugin-react-refresh';
import vitePluginImp from "vite-plugin-imp";
export default defineConfig({
css: {
preprocessorOptions: {
less: {
javascriptEnabled: true,
},
},
},
resolve: {
alias: [
{ find: /^~/, replacement: "" },
],
},
plugins: [
reactRefresh(),
vitePluginImp({
libList: [
{
libName: "antd",
style: (name) => `antd/es/${name}/style`,
},
],
}),
],
});
Also work with #preact/preset-vite.
Ref:
https://github.com/theprimone/vite-react
https://github.com/ant-design/ant-design/issues/7850
https://github.com/vitejs/vite/issues/2185#issuecomment-784637827
Try to import antd styles like this:
vitePluginImp({
libList: [
{
libName: 'antd',
style: (name) => `antd/es/${name}/style`,
},
],
}),
More usage of Vite + React + Ant Design or other UI Library, this repo theprimone/vite-react might give you more or less inspiration.
I am creating a website using django and nuxtjs. I have installed service worker to improve speed. When I unregister service worker in inspect/Application tab, timing of my website in inspect/Network tab looks like this:
When I use service worker opening website at the first time is fine, But when I reload the page or open another page of the website, the request to the server is queued long time. The timing of my website looks like this:
which is queued 1.91 seconds. here describes reasons of queuing a request and all of them is in browser control.
I installed service worker with pwa module which has workbox in its dependencies. My nuxt.config.js file is here:
import pkg from './package'
import {modify_html} from './services/amp/hook';
export default {
mode: 'universal',
/*
** Headers of the page
*/
head: {
title: 'example',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: pkg.description }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
/*
** Customize the progress-bar color
*/
loading: { color: '#fff' },
/*
** Global CSS
*/
css: [
'~/static/css/base.css',
'~/static/css/hooper.css',
'~/static/css/font-awesome/css/all.min.css',
],
/*
** Plugins to load before mounting the App
*/
plugins: [
{ src: '~plugins/ga.js', ssr: false }
],
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://axios.nuxtjs.org/usage
'#nuxtjs/axios',
// Doc: https://bootstrap-vue.js.org/docs/
'bootstrap-vue/nuxt',
'#nuxtjs/pwa',
'#nuxtjs/device',
],
manifest:{
"short_name": "example",
"name": "example",
"icons": [
{
"src": "/static/icon.png",
"type": "image/png",
},
],
"start_url": "/",
"background_color": "white",
"display": "standalone",
"scope": "/",
"theme_color": "white"
},
workbox:{
},
/*
** Axios module configuration
*/
axios: {
// See https://github.com/nuxt-community/axios-module#options
},
/*
** Build configuration
*/
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {
}
},
hooks:{
// This hook is called before generatic static html files for SPA mode
'generate:page': (page) => {
if(page.path.includes('/amp/')){
page.html = modify_html(page.html)
}
},
// This hook is called before rendering the html to the browser
'render:route': (url, page, { req, res }) => {
if(url.includes('/amp/')){
page.html = modify_html(page.html)
}
}
}
}
How can I fix service worker to do not stall new requests?
In the generated precache-manifest.*.js file the URLs all reference relative paths when I need absolute since my app will have some sub-directories as well.
Example of generated file:
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "1d94d834b7044ec6d4e9",
"url": "js/app.js"
},
{
"revision": "632f09e6ed606bbed1f1",
"url": "css/app.css"
},
...
}
When I need it to look like this:
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "1d94d834b7044ec6d4e9",
"url": "/js/app.js"
},
{
"revision": "632f09e6ed606bbed1f1",
"url": "/css/app.css"
},
...
}
I'm using webpack 4.41.0 and workbox-webpack-plugin 4.3.1
Any help would be greatly appreciated! I can add more detail if needed as well.
Here's my webpack config:
let config = {
entry,
stats: {
hash: false,
version: false,
timings: false,
children: false,
errorDetails: false,
entrypoints: false,
performance: inProduction,
chunks: false,
modules: false,
reasons: false,
source: false,
publicPath: false,
builtAt: false
},
performance: { hints: false },
// Valid options: "production" | "development" | "none"
mode: inProduction ? 'production' : 'development',
plugins: [
new CopyPlugin(copyConfig),
new webpack.ProvidePlugin(providers), // Providers, e.g. jQuery
new WebpackNotifierPlugin({ title: 'Webpack' }), // OS notification
new VueLoaderPlugin(), // Vue-loader
new CleanWebpackPlugin(pathsToClean, cleanOptions), // Clean up pre-compile time
new ManifestPlugin(manifestOptions), // Manifest file
new FriendlyErrorsWebpackPlugin({ clearConsole: true }), // Prettify console
new MiniCssExtractPlugin(cssOptions), // Extract CSS files
new WebpackMd5Hash(), // use md5 for hashing
{
/* Laravel Spark RTL support */
apply: (compiler) => {
compiler.hooks.afterEmit.tap('AfterEmitPlugin', (compilation) => {
exec('node_modules/rtlcss/bin/rtlcss.js public/css/app-rtl.css ./public/css/app-rtl.css', (err, stdout, stderr) => {
if (stdout) process.stdout.write(stdout);
if (stderr) process.stderr.write(stderr);
});
});
}
}
],
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader']
},
{
test: /\.s?css$/,
use: [
'style-loader',
{
loader: MiniCssExtractPlugin.loader,
options: { hmr: isHot } // set HMR if flagged
},
'css-loader',
'postcss-loader',
'sass-loader'
]
}
]
},
resolve: {
extensions: ['.js', '.json', '.vue'],
modules: ['node_modules'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'~': path.join(__dirname, 'resources/assets/js'),
jquery: "jquery/src/jquery",
}
},
output: {
filename: 'js/[name].js',
// chunkFilename: inProduction ? 'js/[name].[chunkhash].js' : 'js/[name].js',
path: publicPath,
},
optimization: {
...optimization,
concatenateModules: false,
providedExports: false,
usedExports: false,
},
devtool: inDevelopment ? 'eval-source-map' : false,
devServer: {
headers: {
'Access-Control-Allow-Origin': '*'
},
port: port,
contentBase: publicPath,
historyApiFallback: true,
noInfo: false,
compress: true,
quiet: true,
hot: isHot,
}
}
And my GenerateSW:
new GenerateSW({
// The cache ID
cacheId: 'pwa',
// The path and filename of the service worker file that will be created by the build process, relative to the webpack output directory.
swDest: path.join(publicPath, 'sw.js'),
clientsClaim: true,
skipWaiting: true,
// Files to exclude from the precache
exclude: [/\.(?:png|jpg|jpeg|svg)$/, /\.map$/, /manifest\.json$/, /service-worker\.js$/, /sw\.js$/],
// Default fall-back url
navigateFallback: '/',
// An optional array of regular expressions that restricts which URLs the configured navigateFallback behavior applies to.
// This is useful if only a subset of your site's URLs should be treated as being part of a Single Page App.
navigateFallbackWhitelist: [
/^\/media\//,
/^\/settings\//,
],
// Runtime cache
runtimeCaching: [
{
urlPattern: new RegExp(`${process.env.APP_URL}`),
handler: 'NetworkFirst',
options: {
cacheName: `${process.env.APP_NAME}-${process.env.APP_ENV}`
}
},
{
urlPattern: new RegExp('https://fonts.(googleapis|gstatic).com'),
handler: 'CacheFirst',
options: {
cacheName: 'google-fonts'
}
}
]
}
)
And a couple of defined common variables:
...
// Production flag
const inProduction = process.env.NODE_ENV === 'production'
const inDevelopment = process.env.NODE_ENV === 'development'
// HMR
const isHot = process.argv.includes('--hot')
// Public/webroot path
const publicPath = path.resolve(__dirname, 'public')
// Primary webpack entry point(s)
const entry = {
/*
* JS entry point/Vue base component
* Make sure to import your css files here, e.g. `import '../sass/app.scss'`
*/
app: path.resolve(__dirname, 'resources/assets/js/app.js'),
}
...
For anyone visiting this question, you can use the webpack output.publicPath setting to add a prefix to your manifest URLS like so:
plugins: [
new InjectManifest({}) // Left here just for reference
],
output: {
publicPath: '/' // You can add your prefix here
}
I'm upgrading a project from webpack 1 to 2, and am seeing some strange behavior with postcss-cssnext where some css next features, most notably color() functions and all my #media queries just aren't working anymore.
My webpack config with webpack 2 looks like this. What am I doing wrong here?
{
test: /\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
localIndentName: 'localIdentName=[name]__[local]___[hash:base64:5]',
sourceMap: true,
modules: true,
importLoaders: 1
}
},
{
loader: 'postcss-loader',
options: {
plugins: [
postcssImport({ path: './app/css/common' }),
postcssCssnext({ browsers: ['> 1%', 'last 2 versions'] }),
postcssReporter({ clearMessages: true })
]
}
}
]
}
postcss-loader is probably responsible for this change (1.3.x).
According to doc, you should use a function for "plugins" option.
Or use an array but in a postcss.config.js file.
module.exports = {
module: {
rules: [
{
test: /\.css/,
use: [
…
{
loader: 'postcss-loader',
options: {
plugins: function () {
return [
postcssImport({ path: './app/css/common' }),
postcssCssnext({ browsers: ['> 1%', 'last 2 versions'] }),
postcssReporter({ clearMessages: true })
];
}
}
}
]
}
]
}
}
Or via postcss.config.js
module.exports = {
plugins: [
postcssImport({ path: './app/css/common' }),
postcssCssnext({ browsers: ['> 1%', 'last 2 versions'] }),
postcssReporter({ clearMessages: true })
]
}
(and in webpack)
module.exports = {
module: {
rules: [
{
test: /\.css/,
use: [
…
'postcss-loader',
]
}
]
}
}