I have a stupid simple question that I basically failed to find a good answer for.
I have a nuxt2 project that has a #nuxtjs/router module on it. I have added the module on the buildModules on nuxt.config.js and created router.js on the src folder.
this is my nuxt.config.js file :
ssr: true, // tauri
target: 'static', // tauri
server : {
host:"127.0.0.1",
port: 8001
},
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
...
},
env:{
MEDIA_API:process.env.VUE_APP_MEDIA_API,
API_URL: process.env.API_URL
},
// Global CSS: https://go.nuxtjs.dev/config-css
css: [
],
// Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
plugins: [
...
],
// Auto import components: https://go.nuxtjs.dev/config-components
components: true,
// Modules for dev and build (recommended): https://go.nuxtjs.dev/config-modules
buildModules: [
'#nuxtjs/router'
],
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
...
'#nuxtjs/router',
...
],
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {
extractCSS: true,
plugins: [ // to import jQuery :"
new webpack.ProvidePlugin({
jQuery: 'jquery',
$: 'jquery',
'window.jQuery': 'jquery',
'window.$': 'jquery',
}),
],
standalone: true
},
router: {
middleware: ['auth']
},
auth: {
...
}
and here is my router.js file :
import { parseHTML } from 'jquery';
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
// this is just a function to help me not writing the full path of each page
const page = (path) => () => import(`~/pages/${path}`).then(m => m.default || m)
const routes = [
{path: '/', name: 'home', component: page('index.vue')},
{path: '/login', name: 'login', component: page('login.vue')},
{path: '/players', name: 'allPlayers', component: page('players/index.vue')},
{path: '/players/:id', name: 'singlePlayer', component: page('players/view.vue')},
{path: '/plans', name: 'allPlans', component: page('plans/index.vue')},
{path: '/plans/new', name: 'newPlan', component: page('plans/new.vue')},
{path: '/activities', name : 'allActs', component: page ('activities/index.vue')},
{path: '/activities/new', name: 'newAct', component: page('activities/new.vue')},
{path: '/activityPlayer/:id', name: 'viewActivityPlayer', component: page('activities/viewActivityPlayer')},
{path: '/auth/login', name: 'auth.login', component: page('auth/login')},
{path: '/superAdmin/', name: 'superAdmin', component: page('superAdmin/index.vue')},
{path: '/superAdmin/viewAll', name: 'viewAdmins', component: page('superAdmin/viewAdmins.vue')},
];
export function createRouter() {
return new Router({
routes,
mode: 'history'
})
}
I want to generate full static build to deploy my nuxt app on a tauri build. I was able to successfully deploy a nuxt app that does NOT has that router.js file. The build generate just generate all routes by default in the dist folder.
How can I generate the routes ?
I've tried with the /login path and it's working great as shown in this commit, there was a typo in the path tho (I did tried only for that one since it was an obvious one for me).
I also removed the useless package-lock.json since you use yarn in your project (could be vice-versa of course) and since you should not use both at the same time. Added a few explicit keys in the nuxt.config.js file too.
Commented #nuxtjs/auth-next, ran yarn generate && yarn start and I have successfully access to the given path.
The generated route files are maybe not that friendly (because of their hash) but they are still available in the dist directory. There is a way to make them prettier, you could search for that on Stackoverflow/Google.
Update: it works with the auth middleware too actually.
Related
I have a component library written in vue that I am wrapping up with rollup
I am having an issue with mixins not being wrapped up into the final library. Intially i thought that the path was the issue as most of the mixins are local.
Originally:
import mixin from '../../mixins/color'
Repo folder structure
- dist //output
- src //All files related to the actual component within the library
- components
- comps
- alert //general components
- inputs //input components
- layout //layout components /row/col
- mixins
- utilities
- entry.js //rollup points to this
- ... //I used nuxt to develop the components to focus on SSR so there are more folders but are excluded in the rollup process
Apparently native rollup doesn't like indirect imports so I attempted to add rollup-plugin-includepaths. My understanding is that I would need to mention the paths required in the imports to work correctly.
Therefore, I added rollup-plugin-includepaths to rollup.config.js plugins and added the root path and the output director as the options
includePaths({
paths: ['src/components/', 'src/mixins/', 'src/utilities/'],
extensions: ['.js', '.vue']
}),
**this did not work **
I decided to remove all relative imports and create aliases for each required directory. This did not work either
What is happening is all mixins imported into the component and added as mixin: [mixins] //whatever they may be are not included in the compiled product?!?!?!
What am I missing????
// rollup.config.js
import fs from 'fs'
import path from 'path'
import vue from 'rollup-plugin-vue'
import alias from '#rollup/plugin-alias'
import commonjs from '#rollup/plugin-commonjs'
import replace from '#rollup/plugin-replace'
import babel from 'rollup-plugin-babel'
import { terser } from 'rollup-plugin-terser'
import minimist from 'minimist'
import postcss from 'rollup-plugin-postcss'
import includePaths from 'rollup-plugin-includepaths'
import del from 'rollup-plugin-delete'
// Get browserslist config and remove ie from es build targets
const esbrowserslist = fs
.readFileSync('./.browserslistrc')
.toString()
.split('\n')
.filter(entry => entry && entry.substring(0, 2) !== 'ie')
const argv = minimist(process.argv.slice(2))
const projectRoot = path.resolve(__dirname)
const baseConfig = {
input: 'src/entry.js',
plugins: {
preVue: [
alias({
resolve: ['.js', '.jsx', '.ts', '.tsx', '.vue'],
entries: [
{ find: '#', replacement: path.resolve(projectRoot, 'src') },
{
find: '#mixins',
replacement: path.resolve(projectRoot, 'src', 'mixins')
},
{
find: '#comps',
replacement: path.resolve(projectRoot, 'src', 'components', 'comps')
},
{
find: '#inputs',
replacement: path.resolve(
projectRoot,
'src',
'components',
'inputs'
)
},
{
find: '#utilities',
replacement: path.resolve(projectRoot, 'src', 'utilities')
}
]
}),
includePaths({
paths: ['src/components/', 'src/mixins/', 'src/utilities/'],
extensions: ['.js', '.vue']
}),
commonjs(),
postcss()
],
replace: {
'process.env.NODE_ENV': JSON.stringify('production'),
'process.env.ES_BUILD': JSON.stringify('false')
},
vue: {
css: false,
template: {
isProduction: true
}
},
babel: {
exclude: 'node_modules/**',
extensions: ['.js', '.jsx', '.ts', '.tsx', '.vue']
}
}
}
// ESM/UMD/IIFE shared settings: externals
// Refer to https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency
const external = [
// list external dependencies, exactly the way it is written in the import statement.
// eg. 'jquery'
'vue'
]
// UMD/IIFE shared settings: output.globals
// Refer to https://rollupjs.org/guide/en#output-globals for details
const globals = {
// Provide global variable names to replace your external imports
// eg. jquery: '$'
vue: 'Vue'
}
// Customize configs for individual targets
const buildFormats = []
if (!argv.format || argv.format === 'es') {
const esConfig = {
...baseConfig,
external,
output: {
compact: true,
file: 'dist/comps.esm.js',
format: 'esm',
exports: 'named'
},
plugins: [
del({ targets: 'dist/*' }),
replace({
...baseConfig.plugins.replace,
'process.env.ES_BUILD': JSON.stringify('true')
}),
...baseConfig.plugins.preVue,
vue(baseConfig.plugins.vue),
babel({
...baseConfig.plugins.babel,
presets: [
[
'#babel/preset-env',
{
targets: esbrowserslist
}
]
]
})
]
}
buildFormats.push(esConfig)
}
if (!argv.format || argv.format === 'cjs') {
const umdConfig = {
...baseConfig,
external,
output: {
compact: true,
file: 'dist/comps.ssr.js',
format: 'cjs',
name: 'Components',
exports: 'named',
globals
},
plugins: [
replace(baseConfig.plugins.replace),
...baseConfig.plugins.preVue,
vue({
...baseConfig.plugins.vue,
template: {
...baseConfig.plugins.vue.template,
optimizeSSR: true
}
}),
babel(baseConfig.plugins.babel)
]
}
buildFormats.push(umdConfig)
}
if (!argv.format || argv.format === 'iife') {
const unpkgConfig = {
...baseConfig,
external,
output: {
compact: true,
file: 'dist/comps.min.js',
format: 'iife',
name: 'Components',
exports: 'named',
globals
},
plugins: [
replace(baseConfig.plugins.replace),
...baseConfig.plugins.preVue,
vue(baseConfig.plugins.vue),
babel(baseConfig.plugins.babel),
terser({
output: {
ecma: 5
}
})
]
}
buildFormats.push(unpkgConfig)
}
// Export config
export default buildFormats
Update
I moved the imported components out of the mixin and added them directly to the component that included them and got the same result. Therefore, i really have no clue what needs to happen.
TL;DR
None of the child components are being included in the rolled up dist '.js' files
Sometimes it is hard to include what is relevant and the question above is guilty.
The problem is within the larger component I had imported the children lazily
ex:
components:{
comp: ()=>import('comp') ///Does not work
}
changed to your standard
import comp from 'comp'
components:{
comp
}
I'm trying to implement Module Federation with Angular and NgRX, but i'm facing a problem and don't know how to fix it.
The problem is: when X application lazy loads a module from Y
application that uses Firebase, angular does not recognize the fire
auth provider.
I have 2 apps: Auth and Dashboard.
My Auth application uses firebase to do user login.
The firebase request login is made by a NgRX effect:
import {AngularFireAuth} from '#angular/fire/auth';
#Injectable()
export class AuthEffects {
userLogin$: Observable<Action> = createEffect(() => {
/* effect implementation */
});
constructor(private fireAuth: AngularFireAuth){}
}
The AuthModule imports:
imports: [
/* ...other imports */
StoreModule.forFeature('authState', authReducer),
EffectsModule.forFeature([AuthEffects]),
AngularFireModule.initializeApp(firebaseConfig),
AngularFireAuthModule
]
The Dashboard AppRoutingModule imports:
const routes: Routes = [
{
path: '',
pathMatch: 'full',
loadChildren: () => import('auth/AuthModule').then(m => m.AuthModule)
}
];
#NgModule({
imports: [
RouterModule.forRoot(routes)
],
exports: [RouterModule]
})
When I start only the Auth application, everything works fine and I can do login.
But when I try to use the Auth application remotely, inside Dashboard application, I get this error:
NullInjectorError: StaticInjectorError(AppModule)[InjectionToken angularfire2.app.options]:
StaticInjectorError(Platform: core)[InjectionToken angularfire2.app.options]:
NullInjectorError: No provider for InjectionToken angularfire2.app.options!
Partial Auth - webpack.config.js
plugins: [
new ModuleFederationPlugin({
name: 'auth',
library: {type: 'var', name: 'auth'},
filename: 'remoteEntry.js',
exposes: {
'./AuthModule': './src/app/login/auth.module.ts',
'./AuthComponent': './src/app/login/auth.component.ts',
'./AuthActions': './src/app/store/actions/auth.actions.ts',
'./AuthReducer': './src/app/store/reducers/auth.reducer.ts',
'./AuthEffects': './src/app/store/effects/auth.effects'
},
shared: {
...dependencies,
'#angular/core': {
requiredVersion: dependencies['#angular/core'],
singleton: true,
},
'#angular/common': {
requiredVersion: dependencies['#angular/common'],
singleton: true,
},
'#angular/router': {
requiredVersion: dependencies['#angular/router'],
singleton: true,
}
}
})
]
Parial Dashboard - webpack.config.js
plugins: [
new ModuleFederationPlugin({
name: 'dashboard',
library: {type: 'var', name: 'dashboard'},
filename: 'remoteEntry.js',
remotes: {
auth: 'auth',
},
shared: {
...dependencies,
'#angular/core': {
requiredVersion: dependencies['#angular/core'],
singleton: true,
},
'#angular/common': {
requiredVersion: dependencies['#angular/common'],
singleton: true,
},
'#angular/router': {
requiredVersion: dependencies['#angular/router'],
singleton: true,
}
}
})
]
I tried to resolve it by myself, but Module Federation is a new thing and we have little posts about.
Can someone help me? If you came until here, thank you very much! :D
Solved!
Thanks Zack Jackson, I could solve the problem.
Solution:
https://github.com/module-federation/module-federation.github.io/issues/14#issuecomment-672647713
I have a Vue locally, the main /index.html is the webroot but when I deploy, I want the subfolder /stats to be the root (and all my routes to still work).
Can I do this without manually changing my router/index.js?
vue.config.js
// this doesn't seem to work
module.exports = {
publicPath: process.env.NODE_ENV === "production" ? "/stats/" : "/",
};
router.js
const routes = [
{
path: "/",
name: "HomeView",
component: HomeView,
},
{
path: "/grid",
name: "GridView",
component: GridView,
},
...
]
The only recommendation I'd make sure you set router base property to match your publicPath
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL, // 👈 set the "base" property here
routes
})
Is there a way to remove some routes with their linked components from production build of Vue app?
In my app I have manager interface that only I use so there is no need to have it's logic in the production build. I want to avoid having any of manager's code actually used in the production build as I can use the manager page only during development on localhost.
Here is simple example what I have now. The managerCheck tests if user is manager to allow user to enter or to redirect him back to the homepage. This is probably enough as it is also combined with check in MongoDB but I still would love to not includes manager's components logic inside production build as ManagerView includes pretty powerful functions and it is better to be safe than sorry.
// router.js
// ... some imports
const userCheck = (to, from, next) => store.getters['user/user'] ? next() : next({path: '/login'})
const managerCheck = (to, from, next) => store.getters['user/manager'] ? next() : next({path: '/'})
export default new Router({
mode: 'hash',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'App Name',
component: MainView,
},
{
path: '/user',
name: 'User',
component: UserView,
beforeEnter: userCheck
},
{
path: '/manager',
name: 'Manager',
component: ManagerView,
beforeEnter: managerCheck
}
})
In production, unnecessary routes can be filtered out.
Routes can be defined with productionAvailable flag.
routes: [
{
path: '/',
name: 'App Name',
component: MainView,
productionAvailable: true,
},
{
path: '/user',
name: 'User',
component: UserView,
beforeEnter: userCheck,
productionAvailable: true,
},
{
path: '/manager',
name: 'Manager',
component: ManagerView,
beforeEnter: managerCheck,
productionAvailable: false,
}
}]
Then filter it when exporting if the node env is set to production.
export default new Router({
mode: 'hash',
base: process.env.BASE_URL,
routes: process.env.NODE_ENV === 'production' ? routes.filter((route) => route.productionAvailable) : routes,
})
I would do something like this:
// router.js
// ... some imports
const userCheck = (to, from, next) => store.getters['user/user'] ? next() : next({path: '/login'})
const managerCheck = (to, from, next) => store.getters['user/manager'] ? next() : next({path: '/'})
const clientRoutes = [
{
path: '/',
name: 'App Name',
component: MainView,
},
{
path: '/user',
name: 'User',
component: UserView,
beforeEnter: userCheck
}
]
const managerRoutes = []
// you may have to look into process.env to set this condition correctly
if (process.env.NODE_ENV !== 'production') {
managerRoutes.push({
path: '/manager',
name: 'Manager',
component: ManagerView,
beforeEnter: managerCheck
})
}
export default new Router({
mode: 'hash',
base: process.env.BASE_URL,
routes: [...clientRoutes, ...managerRoutes]
})
process.env: https://cli.vuejs.org/guide/mode-and-env.html#modes
I;m wondering if it's possible to build a bundle with some javascript files but without dependencies?
I want to have small bundles with React components (each react component in my case is builded from few react components, for example Comment component incldues comment box, list, and form),
I can split React components to a separate files by specifying few entry points in webpack, but if I have:
1. Component comment
2. Component newsletter
and both of them require ReactDOM, files which will be generated will have like 600kb, where my react components contain only ~100 lines of js code.
I would like to have one more file which will contain all the code which would come from "require('react-dom'), and those two files which will only have the React component code. is that possible?
My current setup:
'use strict';
import path from 'path';
import CommonsChunkPlugin from "webpack/lib/optimize/CommonsChunkPlugin";
module.exports = {
entry: {
app: "./app.js",
newsletter: "./components/renderers/newsletter.renderer.js",
comment: "./components/renderers/comment.renderer.js"
},
output: {
path: path.join(__dirname),
filename: "built/[name].entry.js"
},
devtool: 'sourcemaps',
cache: true,
debug: true,
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: [/(node_modules)/],
loader: 'babel'
}
],
resolve: {
extensions: ['', '.js', '.jsx']
}
},
plugins: [
new CommonsChunkPlugin({
name: "comment.js",
chunks: ["comment", "app"],
minChunks: 2
}),
new CommonsChunkPlugin({
name: "newsletter.js",
chunks: ["newsletter", "app"],
minChunks: 2
})
]
};
Comment.renderer.js:
import CommentBox from './../comment/commentBox';
ReactDOM.render(
<CommentBox/>,
document.getElementById("comment")
);
Newsletter.renderer.js:
import Newsletter from './../newsletter/newsletter';
ReactDOM.render(
<Newsletter/>,
document.getElementById("newsletter")
);
app.js:
'use strict';
import React from 'react';
import ReactDOM from 'react-dom';
import client from './lib/client';
Ok I've managed how to do that:
import path from 'path';
import CommonsChunkPlugin from "webpack/lib/optimize/CommonsChunkPlugin";
module.exports = {
entry: {
vendor: ["react","react-dom", "underscore"],
comment: "./components/renderers/comment.renderer.js",
newsletter: "./components/renderers/newsletter.renderer.js"
},
output: {
path: path.join(__dirname),
filename: "built/[name].bundle.js"
},
devtool: 'sourcemaps',
cache: true,
debug: true,
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: [/(node_modules)/],
loader: 'babel'
}
],
resolve: {
extensions: ['', '.js', '.jsx']
}
},
plugins: [
new CommonsChunkPlugin({
name: "vendor",
minChunks: Infinity
})
]
};
this part:
minChunks: Infinity
will ensure that code included in bundle "vendor" is not included in any other bundle. Thanks to this approach, comment and newsletter will contain only my React components.
I use following code in webpack.config.js to exclude the external dependencies from bundle.
module.exports = {
...
...
externals:{
"react": "React",
"react-dom": "ReactDOM"
},
...
...
}
I found this answer from this link
To complement #AnandShanbhag's answer, you can take all the dependencies from package.json and turn them into externals with a function:
module.exports = {
...
// put everything inside package.json dependencies as externals
externals: Object.keys(require('./package.json').dependencies)
.reduce(
function (acc, cur) {
acc[cur] = cur
return acc
},
new Object()
),
...
}