I am looking for some best practices for publishing and developing nuxt plugins. I would like to write a plugin which gives our web applications the possibility to request oauth tokens from everywhere. I have written this plugin localy in my project and it works. Now my target is to move the code to a seperate plugin project and upload it to npm so every one in my company might use it easily. Are there any guides how to setup a nuxt plugin project? I found several guides for creating vue-plugins but the structure of them are a bit different to nuxt. I do not have a install method. Because my plugin simply wraps vuex store methods defined in oAuthStore.js as global methods, which can be used when I register my plugin in nuxt.config.js.
Vue plugins seems to work a bit different.
I upload a vue-plugin with an install method. When I try to import it and run my application on dev server (npm run dev) i always get the error message:
This dependency was not found: * my-plugin in ./plugins/vuex-persisted.js friendly-errors 16:55:24
friendly-errors 16:55:24
To install it, you can run: npm install --save my-plugin
My plugin has been uploaded to npm correctly and I have used it by executing npm install --save my-plugin so it has an entry on dependency list in package.json.
When I try to npm-link my-plugin I get the same error. This is the only way I know for rapid prototyping because I do not want a npm publish every time I want to test something. Does everyone know a way for a better developing workflow for working on nuxt plugins?
Thanks for any help.
Best regards
Moritz
/** oAuthPlugin.js **/
import oAuthStore from './oAuthStore.js'
import Cookies from 'js-cookie'
import createPersistedState from 'vuex-persistedstate'
export default ({store, isHMR, app}, inject) => {
app.store.registerModule('oAuth', oAuthStore );
var me = app;
inject('getOAuthCredentials', () => {
var data = {};
if(app.$store) {
var data = app.$store.getters["oAuth/getAuthCredentials"];
}
return data;
});
inject('requestOAuthCredentials', (data) => {
if(me.store) {
me.store.commit("oAuth/requestOAuthCredentials", data);
}
});
if (isHMR) return
// add persisted state as a vue mounted mixin
if (!app.mixins) {
app.mixins = []
}
app.mixins.push({mounted () {
createPersistedState({
key: 'vuex-persisted',
paths: ['oAuth'],
storage: {
getItem: key => Cookies.get(key),
setItem: (key, value) => Cookies.set(key, value, {expires: 3}),
removeItem: key => Cookies.remove(key)
}
})(store);
}});
}
/** nuxt.config.js **/
/*
** Plugins to load before mounting the App
*/
plugins: [
{ src: '~/plugins/vuex-persisted', ssr: false },
{ src: '~/plugins/oAuthPlugin.js' }
],
Related
Is it possible to host a Flutter web app on a local environment using a Flutter desktop-based app?
The google-search for a solution like this can be difficult, since it involves many keywords that lead to similar situations (online hosting when you need a local solution, command-line only solution, and so on).
After some digging, I ended up using the shelf package to deploy my own Flutter web app on a local network. I developed this for Windows only, so I can't guarantee it will work on other platforms.
First thing to do is obviously adding the shelf package in your pubspec.yaml: after that, this is how my main method looks like
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf_router/shelf_router.dart' as shelf_router;
[...]
void main() async{
[...]
var secureContext = SecurityContext();
try {
//privKey and cert are the String names of the two files for the SSL connection,
//placed in the root directory of the flutter project or along with the .exe file (when released)
secureContext.usePrivateKey(privKey);
secureContext.useCertificateChain(cert);
} catch (error) {
logger.e("Error on init SecurityContext");
}
try {
//this is the handler that deploys the files contained in 'webAppFolder': I just simply pasted the result of
//the flutter webapp building inside (the index.html file is the default one for flutter web)
//and put the folder in the root of the flutter project (or, again, in the same folder with the .exe file when released)
final _staticHandler = createStaticHandler("webAppFolder", defaultDocument: 'index.html');
//this I kept just for a reminder on how to deploy a static page, if needed
final _router = shelf_router.Router()
..get(
'/time',
(request) => shelf.Response.ok(DateTime.now().toUtc().toIso8601String()),
);
final cascade = shelf.Cascade()
.add(_staticHandler)
.add(_router);
try {
var server = await shelf_io.serve(
cascade.handler,
InternetAddress.anyIPv4,
mainPort, //this is the number of the port on which the webapp is deployed (I load this from a .ini file beforehand
securityContext: secureContext,
);
// Enable content compression
server.autoCompress = true;
logger.i("Serving at https://${server.address.host}:${server.port}");
} catch (err) {
logger.e("Error while serving");
logger.e(err.toString());
}
} catch (err) {
logger.e("Error while creating handler");
logger.e(err.toString());
}
runApp(MaterialApp(
[...]
This is the part related to the deploy of a web app: since the flutter desktop app already provides a GUI, I used that to add some maintenance and testing utilities to check if everything is working fine.
For more details regarding shelf, refer to their API on their pub.dev page.
I'm trying to setup Agora for live streaming in my nuxtjs app. But it gives an error saying plugin not recognized in the console and I can't seem to get past this issue. Did anyone encounter similar issues? My nuxt version is "nuxt": "^2.15.8" and agora "agora-rtc-sdk-ng": "^4.13.0". The error I'm encountering now is:
I've imported the plugin in agora.js file in my plugins folder.
import Vue from "vue";
import { AgoraRTC } from 'agora-rtc-sdk-ng';
Vue.use(AgoraRTC);
And the nuxt config.
{
src: "~/plugins/agora.js",
ssr: false,
mode: 'client'
}
EDIT:
If I update the agora.js file with this code:
import Vue from "vue";
import AgoraRTC from 'agora-rtc-sdk-ng';
Vue.use(AgoraRTC);
I get the error: ReferenceError: AgoraRTC is not defined.
Am I missing something? Also it would be a great help if anyone could give reference to a demo build with nuxt.
After finding no solution to this, I contacted the support team of Agora. They had been a great help!
The problem was with Vue.use(AgoraRTC). For some reason this wasn't working. So I had to inject it in the app.
First I replaced these sections form plugins/agora.js file:
import Vue from "vue";
import AgoraRTC from 'agora-rtc-sdk-ng';
Vue.use(AgoraRTC);
and nuxt.config.js file:
{
src: "~/plugins/agora.js",
ssr: false,
mode: 'client'
}
With this:
import AgoraRTC from "agora-rtc-sdk-ng"
export default ({app}, inject) => {
inject("AgoraRTC", AgoraRTC)
}
and:
{
src: "~/plugins/agora.js",
mode: 'client'
}
Finally the AgoraRTC variable is accessible in the components as this.$AgoraRTC.
Reference to inject in $root from Nuxt docs
Thanks to the support team of Agora
This question already has an answer here:
Fetch error when building Next.js static website in production
(1 answer)
Closed last year.
I have a very simple NextJS 9.3.5 project.
For now, it has a single pages/users and a single pages/api/users that retrieves all users from a local MongoDB table
It builds fine locally using 'next dev'
But, it fails on 'next build' with ECONNREFUSED error
page/users
import fetch from "node-fetch"
import Link from "next/link"
export async function getStaticProps({ params }) {
const res = await fetch(`http://${process.env.VERCEL_URL}/api/users`)
const users = await res.json()
return { props: { users } }
}
export default function Users({ users }) {
return (
<ul>
{users.map(user => (
<li key={user.id}>
<Link href="/user/[id]" as={`/user/${user._id}`}>
<a>{user.name}</a>
</Link>
</li>
))}
</ul>
);
}
pages/api/users
import mongoMiddleware from "../../lib/api/mongo-middleware";
import apiHandler from "../../lib/api/api-handler";
export default mongoMiddleware(async (req, res, connection, models) => {
const {
method
} = req
apiHandler(res, method, {
GET: (response) => {
models.User.find({}, (error, users) => {
if (error) {
connection.close();
response.status(500).json({ error });
} else {
connection.close();
response.status(200).json(users);
}
})
}
});
})
yarn build
yarn run v1.22.4
$ next build
Browserslist: caniuse-lite is outdated. Please run next command `yarn upgrade`
> Info: Loaded env from .env
Creating an optimized production build
Compiled successfully.
> Info: Loaded env from .env
Automatically optimizing pages ..
Error occurred prerendering page "/users". Read more: https://err.sh/next.js/prerender-error:
FetchError: request to http://localhost:3000/api/users failed, reason: connect ECONNREFUSED 127.0.0.1:3000
Any ideas what is going wrong ? particularly when it works fine with 'next dev' ?
Thank you.
I tried the same few days ago and didn't work... because when we build the app, we don't have localhost available... check this part of the doc - https://nextjs.org/docs/basic-features/data-fetching#write-server-side-code-directly - that said: "You should not fetch an API route from getStaticProps..." -
(Next.js 9.3.6)
Just to be even more explicit on top of what Ricardo Canelas said:
When you do next build, Next goes over all the pages it detects that it can build statically, i.e. all pages that don't define getServerSideProps, but which possibly define getStaticProps and getStaticPaths.
To build those pages, Next calls getStaticPaths to decide which pages you want to build, and then getStaticProps to get the actual data needed to build the page.
Now, if in either of getStaticPaths or getStaticProps you do an API call, e.g. to a JSON backend REST server, then this will get called by next build.
However, if you've integrated both front and backend nicely into a single server, chances are that you have just quit your development server (next dev) and are now trying out a build to see if things still work as sanity check before deployment.
So in that case, the build will try to access your server, and it won't be running, so you get an error like that.
The correct approach is, instead of going through the REST API, you should just do database queries directly from getStaticPaths or getStaticProps. That code never gets run on the client anyways, only server, to it will also be slightly more efficient than doing a useless trip to the API, which then calls the database indirectly. I have a demo that does that here: https://github.com/cirosantilli/node-express-sequelize-nextjs-realworld-example-app/blob/b34c137a9d150466f3e4136b8d1feaa628a71a65/lib/article.ts#L4
export const getStaticPathsArticle: GetStaticPaths = async () => {
return {
fallback: true,
paths: (await sequelize.models.Article.findAll()).map(
article => {
return {
params: {
pid: article.slug,
}
}
}
),
}
}
Note how on that example, both getStaticPaths and getStaticProps (here generalized HoC's for reuse, see also: Module not found: Can't resolve 'fs' in Next.js application ) do direct database queries via sequelize ORM, and don't do any HTTP calls to the external server API.
You should then only do client API calls from the React components on the browser after the initial pages load (i.e. from useEffect et al.), not from getStaticPaths or getStaticProps. BTW, note that as mentioned at: What is the difference between fallback false vs true vs blocking of getStaticPaths with and without revalidate in Next.js SSR/ISR? reducing client calls as much as possible and prerendering on server greatly reduces application complexity.
I'm attempting use react-router in my brunch/babel setup. In my app.js I have:
import React from "react"
import ReactDOM from "react-dom"
import { Router, Route, Link } from "react-router"
This however gives me:
Uncaught Error: Cannot find module "history/lib/createHashHistory" from "react-router/Router"
When looking at the referenced line I see:
var _historyLibCreateHashHistory = require('history/lib/createHashHistory');
When inspecting the app.js that's generated via brunch I see:
require.register('history/createBrowserHistory', function(exports,req,module) {
...
});
How do I go about fixing this so that createBrowserHistory gets imported properly?
The module history is listed as a peer dependency by react-router, which means that you need to install it yourself through the command npm install history --save.
I am phasing ember into a project that has its content linking from the server root (as it is in prod).
E.g I have a html files with links like this:
<img src="/content/foo.svg">
How can I set up ember cli so that when I run ember server these URL's will work, without having to move the ember-cli project to the directory in my file system containing /content. I could get round this by moving content into the ember folder but don't want to do this at present..
my folder structure:
/content
/anotherFolder
/theEmberCliApp
/app
/etc etc..
but when I run it I get this error:
[Report Only] Refused to connect to 'ws://127.0.0.1:35729/livereload' because it violates the following Content Security Policy directive: "connect-src 'self' ws://localhost:35729 ws://0.0.0.0:35729".
livereload.js?ext=Chrome&extver=2.0.9:193__connector.Connector.Connector.connect livereload.js?ext=Chrome&extver=2.0.9:193Connector livereload.js?ext=Chrome&extver=2.0.9:176LiveReload livereload.js?ext=Chrome&extver=2.0.9:862(anonymous function) livereload.js?ext=Chrome&extver=2.0.9:1074(anonymous function)
I think the issue is this: baseURL: '../../' how can I get round this? For other non ember sites I just point apaches httpdconfig to the location of the parent of content, but I don't want to stick the whole ember cli project in there.
my environment.js:
/* jshint node: true */
module.exports = function(environment) {
var ENV = {
modulePrefix: 'ember-app',
environment: environment,
baseURL: '../../',
locationType: 'auto',
EmberENV: {
FEATURES: {
// Here you can enable experimental features on an ember canary build
// e.g. 'with-controller': true
}
},
APP: {
// Here you can pass flags/options to your application instance
// when it is created
}
};
if (environment === 'production') {
}
return ENV;
};