Deploying NextJS app on AWS Amplify with Styled Components - ERROR: Cannot read property 'useState' of null / Error occurred prerendering page "/404" - amazon-web-services

When I'm trying to deploy my NextJS (with Styled Components) application on AWS Amplify I'm getting these errors:
Error occurred prerendering page "/404"
TypeError: Cannot read property 'useState' of null
And that's all!
My _document.tsx
import React from 'react';
import Document, { DocumentContext, Head, Html, Main, NextScript } from 'next/document';
import { ServerStyleSheet } from 'styled-components';
// eslint-disable-next-line #typescript-eslint/ban-ts-comment
// #ts-expect-error
class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />),
enhanceComponent: (Component) => Component
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
};
} finally {
sheet.seal();
}
}
render() {
return (
<Html lang="pl">
<Head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="" />
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght#300;400;500;600;700&display=swap" rel="stylesheet" />
<meta name="viewport" content="width=device-width" />
<meta charSet="utf-8" />
</Head>
<body>
<main aria-live="polite" aria-atomic="true">
<Main />
</main>
<NextScript />
</body>
</Html>
);
}
}
export default MyDocument;
My package.json
{
"name": "app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"test": "jest --coverage --passWithNoTests",
"lint": "eslint src --fix"
},
"dependencies": {
"#shared/ui": "*",
"next": "12.1.6",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-router": "^6.3.0",
"react-router-dom": "^6.3.0",
"styled-components": "^5.3.5"
},
"devDependencies": {
"#types/node": "17.0.35",
"#types/react": "18.0.14",
"#types/react-dom": "18.0.5",
"#types/styled-components": "^5.1.25",
"babel-plugin-styled-components": "^2.0.7",
"eslint": "^8.16.0",
"next-transpile-modules": "^9.0.0",
"prettier": "^2.6.2",
"typescript": "4.7.2"
}
}
My babel configuration
{
"presets": ["next/babel"],
"plugins": [
[
"styled-components",
{
"ssr": true,
"displayName": true,
"preprocess": false
}
]
]
}
It seems like something with SC rendering, but I don't know how to fix that. Please help.

Related

Angular "Uncaught (in promise): ChunkLoadError: Loading chunk 12 failed." error

I have recently rewritten my angular application. The previous project worked fine and I've not changed my django or apache2 configuration as it should just slip in.
n.b. I have changed the django home.html to include "-es2015" in the appropriate file names.
I'm currently getting the below errors in the inspector
Resource interpreted as Stylesheet but transferred with MIME type application/javascript: "http://146.148.41.45/static/assets/js/frontendwikiconverter.js". 146.148.41.45/:33
GET https://p.typekit.net/p.css?s=1&k=oov2wcw&ht=tk&f=39203&a=2613646&app=typekit&e=css net::ERR_CONNECTION_REFUSED oov2wcw.css:1
Uncaught SyntaxError: Invalid or unexpected token styles.css:1
Uncaught SyntaxError: Unexpected token '<' 12-es5.js:2
ERROR Error: Uncaught (in promise): ChunkLoadError: Loading chunk 12 failed. main-es5.js:1
My app.module:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule, NO_ERRORS_SCHEMA } from '#angular/core';
import { LocationStrategy, HashLocationStrategy } from '#angular/common';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { PerfectScrollbarModule } from 'ngx-perfect-scrollbar';
import { PerfectScrollbarConfigInterface } from 'ngx-perfect-scrollbar';
import { ToastrModule } from 'ngx-toastr';
import { JwtTokenService } from './services/jwt-token.service'
import { IconModule, IconSetModule, IconSetService } from '#coreui/icons-angular';
import { LocalStorageService } from './services/local-storage-service.service';
import { NgxSmartModalModule } from 'ngx-smart-modal';
const DEFAULT_PERFECT_SCROLLBAR_CONFIG: PerfectScrollbarConfigInterface = {
suppressScrollX: true
};
import { AppComponent } from './app.component';
import { DefaultLayoutComponent } from './containers';
import { CommonModule } from "#angular/common";
import {AddToPlannerModule} from './views/planner/add-to-planner.module'
import { TooltipModule } from 'ngx-bootstrap/tooltip';
const APP_CONTAINERS = [
DefaultLayoutComponent
];
import {
AppAsideModule,
AppBreadcrumbModule,
AppHeaderModule,
AppFooterModule,
AppSidebarModule,
} from '#coreui/angular';
import { AppRoutingModule } from './app.routing';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { TabsModule } from 'ngx-bootstrap/tabs';
import { ChartsModule } from 'ng2-charts';
import { AuthorizeGuard } from './services/authorize-guard.service';
import { TokenInterceptor } from './services/http.interceptor'
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
import { HttpClientModule, HTTP_INTERCEPTORS } from '#angular/common/http';
import { DatePipe } from '#angular/common';
import { IsAdmin } from './services/can-activate-guard.service';
#NgModule({
imports: [
BrowserModule,
CommonModule,
TooltipModule.forRoot(),
BrowserAnimationsModule,
AppRoutingModule,
AppAsideModule,
AppBreadcrumbModule.forRoot(),
AppFooterModule,
AppHeaderModule,
AppSidebarModule,
PerfectScrollbarModule,
BsDropdownModule.forRoot(),
TabsModule.forRoot(),
ChartsModule,
IconModule,
IconSetModule.forRoot(),
HttpClientModule,
NgxSmartModalModule.forRoot(),
ToastrModule.forRoot({
positionClass :'toast-bottom-right'
}),
NgbModule,
AddToPlannerModule
],
declarations: [
AppComponent,
...APP_CONTAINERS,
],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true,
deps: [JwtTokenService]
},
{
provide: LocationStrategy,
useClass: HashLocationStrategy
},
IconSetService,
JwtTokenService,
LocalStorageService,
AuthorizeGuard,
DatePipe,
IsAdmin
],
schemas: [
NO_ERRORS_SCHEMA
],
bootstrap: [
AppComponent
],
entryComponents: [],
exports: [
//AddToPlannerComponent
]
})
export class AppModule { }
Routing Module:
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
// Import Containers
import { DefaultLayoutComponent } from './containers/default-layout/default-layout.component';
import { P404Component } from './views/site-admin/p404/p404.component';
import { P500Component } from './views/site-admin/p500/p500.component';
import { SignInComponent } from './views/useradmin/sign-in/sign-in.component';
import { JoinComponent } from './views/useradmin/join/join.component';
import { HomeComponent } from './views/general/home/home.component'
export const routes: Routes = [
{
path: '404',
component: P404Component,
data: {
title: 'Page 404'
}
},
{
path: '500',
component: P500Component,
data: {
title: 'Page 500'
}
},
{
path: 'signin',
component: SignInComponent,
data: {
title: 'Sign In'
}
},
{
path: 'join',
component: JoinComponent,
data: {
title: 'Join KeyStageWiki'
}
},
{
path: '',
redirectTo: 'home',
pathMatch: 'full'
},
{
path: '',
component: DefaultLayoutComponent,
data: {
title: 'KeyStageWiki'
},
children: [
{
path: 'home',
loadChildren: () => import('./views/general/home/home.module').then(m => m.HomeModule)
},
{
path: 'ad-manager',
loadChildren: () => import('./views/admin/ad-manager/ad-manager.module').then(m => m.AdManagerModule)
},
{
path: 'general',
loadChildren: () => import('./views/general/general.module').then(m => m.GeneralModule)
},
{
path: 'planner',
loadChildren: () => import('./views/planner/planner.module').then(m => m.PlannerModule)
},
{
path: 'user',
loadChildren: () => import('./views/useradmin/user-admin.module').then(m => m.UserAdminModule)
},
{
path: 'wiki',
loadChildren: () => import('./views/wiki/wiki.module').then(m => m.WikiModule)
},
{
path: 'lessons',
loadChildren: () => import('./views/lessons/lessons.module').then(m => m.LessonsModule)
},
]
},
{ path: '**', component: P404Component }
];
#NgModule({
imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })],
exports: [RouterModule]
})
export class AppRoutingModule { }
home.html in the Django project:
{% load static %}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="{% static 'assets/img/keystagewiki.png' %}">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<!-- <link rel="stylesheet" href="{% static 'ang/styles.css' %}"> -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
<script src="https://cdn.ckeditor.com/4.7.0/full-all/ckeditor.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="https://cdn.ckeditor.com/4.5.11/full-all/ckeditor.js"></script>
<link rel="stylesheet" href="https://use.typekit.net/oov2wcw.css">
<link rel="stylesheet" href="{% static 'assets/css/indigo-pink.css' %}">
<link rel="stylesheet" href="{% static 'assets/css/angular-calendar.css' %}">
<link rel="stylesheet" href="{% static 'assets/js/frontendwikiconverter.js' %}">
<link href="../css/style.css" type="text/scss" rel="stylesheet">
<link rel="stylesheet" href="{% static 'assets/css/ksw.css' %}">
</head>
<body style="max-width:1250px;margin:auto;" >
<app-root>
<img src="https://media.giphy.com/media/MDrmyLuEV8XFOe7lU6/giphy.gif" alt="Loading..." style="position:fixed; top:50%; left:50%; transform: translate(-50%, -50%);">
</app-root>
<script type="text/javascript" src="{% static 'ang/runtime.js' %}" defer></script>
<script type="text/javascript" src="{% static 'ang/polyfills.js' %}" defer></script>
<script type="text/javascript" src="{% static 'ang/main.js' %}" defer></script>
<script type="text/javascript" src="{% static 'ang/vendor.js' %}" defer></script>
<script type="text/javascript" src="{% static 'ang/styles.css' %}" defer></script>
<script type="text/javascript" src="{% static 'ang/scripts.js' %}" defer></script>
</body>
</html>
I'm very stuck, search and tried everything listed online. No progress. Any advise?

Loading AWS sdk in chrome extension

In my chrome extension, I was trying to load the AWS Cognito js SDK in the popup type iframe HTML where the HTML is bundled by react, now the problem is I am not able to access AWS instance or ( window.AWS ) in my useEffect to perform user authentication
PS: I tried to get the window object too like below but it was hard luck.
chrome.tabs.query(
{active: true, windowType: 'normal', currentWindow: true},
function (d) {
chrome.tabs.get(d[0].id, function (tab) {
chrome.windows.get(tab.windowId, function (win) {
console.log('App -> win', win)
debugger // THIS IS THE WINDOW OBJECT
})
})
},
)
from background_script.js I get a trigger for on click extension icon
function gotMessage(payload) {
if (payload.message === 'SIGNAL_TAB') {
iframe.src = chrome.extension.getURL('./index.html')
document.body.appendChild(iframe)
toggle()
}
}
In Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.831.0.min.js"></script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
In my App.js
function App() {
useEffect(() => {
console.log('App -> window.AWS', window)
chrome.tabs.query(
{active: true, windowType: 'normal', currentWindow: true},
function (d) {
console.log("App -> d", d)
chrome.tabs.get(d[0].id, function (tab) {
chrome.windows.get(tab.windowId, function (win) {
console.log('App -> win', win)
})
})
},
)
return <SomeJSX />
}
Here is my index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
Manifest.json
{
"manifest_version": 2,
"name": "Elixir AI",
"description": "Elixir AI description",
"version": "1.0",
"permissions": ["tabs", "bookmarks", "unlimitedStorage", "storage", "http://*/", "https://*/"],
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["./content.js"]
}
],
"web_accessible_resources": ["index.html"],
"background": {
"scripts": ["./background.js"]
},
"browser_action": {
"default_icon": "elixir.png"
},
"content_security_policy": "script-src 'self' 'sha256-Vkb/pSN52JgiWSIfh1wav6XGzM3ULeZ5d9VaHeA5JQ8='; object-src 'self'"
}
Background.js
chrome.browserAction.onClicked.addListener(buttonClicked)
chrome.tabs.query({active: true, lastFocusedWindow: true}, (tabs) => {
let url = tabs[0].url
new Promise((res, rej) => {
window.linkedin_url = url
localStorage.setItem('linkedin_url', url)
res(url)
})
})
function buttonClicked(tab) {
var payload = {
id: tab.id,
tabs: chrome.tabs,
eventTab: tab,
message: "SIGNAL_TAB",
linkedin_url: tab.url
}
chrome.tabs.sendMessage(tab.id, payload)
}

Cannot shallowMount a Vue Compoent for unit testing

I'm new to Vue, but have a project with a login page. I can run it fine, but I'm trying to retro-add unit-testing (I know, I'm doing this backwards). I'm using Mocha + Chai and vue test utils. when I try to shallowMount I get an error saying that it cannot read a property. Here is the full error text:
1) Login
Has login text:
TypeError: Cannot read property 'email' of undefined
at Proxy.render (webpack:///./src/views/user/Login.vue?./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options:65:34)
at VueComponent.Vue._render (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:3640:22)
at VueComponent.updateComponent (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4168:21)
at Watcher.get (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4582:25)
at new Watcher (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4569:45)
at mountComponent (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4175:3)
at VueComponent.Vue.$mount (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:8512:10)
at init (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:3232:13)
at createComponent (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:6053:9)
at createElm (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:6001:9)
at VueComponent.patch [as __patch__] (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:6611:7)
at VueComponent.Vue._update (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4039:19)
at VueComponent.updateComponent (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4168:10)
at Watcher.get (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4582:25)
at new Watcher (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4569:45)
at mountComponent (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:4175:3)
at VueComponent.Vue.$mount (webpack:///./node_modules/vue/dist/vue.runtime.esm.js?:8512:10)
at mount (webpack:///./node_modules/#vue/test-utils/dist/vue-test-utils.js?:13265:21)
at shallowMount (webpack:///./node_modules/#vue/test-utils/dist/vue-test-utils.js?:13278:10)
at Context.eval (webpack:///./tests/unit/login.spec.js?:17:87)
at processImmediate (internal/timers.js:439:21)
Here is my packages file:
{
"name": "client",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e",
"test": "mochapack --webpack-config webpack.config.js --require tests/setup.js tests/**/*.spec.js"
},
"dependencies": {
"axios": "^0.19.2",
"core-js": "^3.6.4",
"vue": "^2.6.11",
"vue-axios": "^2.1.5",
"vue-router": "^3.1.5",
"vuelidate": "^0.7.5",
"vuetify": "^2.1.0",
"vuex": "^3.1.2"
},
"devDependencies": {
"#vue/cli-plugin-babel": "^4.2.0",
"#vue/cli-plugin-e2e-cypress": "^4.2.0",
"#vue/cli-plugin-router": "^4.2.0",
"#vue/cli-plugin-unit-mocha": "^4.2.0",
"#vue/cli-plugin-vuex": "^4.2.0",
"#vue/cli-service": "^4.2.0",
"#vue/test-utils": "^1.0.0-beta.31",
"chai": "^4.1.2",
"jsdom": "^16.1.0",
"jsdom-global": "^3.0.2",
"mocha": "^7.0.1",
"mochapack": "^1.1.13",
"node-sass": "^4.12.0",
"sass": "^1.19.0",
"sass-loader": "^8.0.2",
"vue-cli-plugin-vuetify": "^2.0.4",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.3.0"
}
}
Here is my component code:
<template>
<v-container fluid fill-height>
<v-layout align-center justify-center>
<v-flex xs12 sm8 md4>
<v-card class="elevation-12">
<v-toolbar color="primary" dark flat>
<v-toolbar-title>Login form</v-toolbar-title>
</v-toolbar>
<v-card-text>
<v-form #submit.prevent="login">
<v-text-field
autofocus
v-model="email"
label="Email"
prepend-icon="mdi-account-circle"
#blur="$v.email.$touch()"
/>
<div class="red--text text--lighten-1" v-if="$v.email.$error">
<div v-if="!$v.email.required">
<v-icon color="red">mdi-alert-circle-outline</v-icon>
Email is required
</div>
<div v-if="!$v.email.email">
<v-icon color="red">mdi-alert-circle-outline</v-icon>
Invalid email address.
</div>
</div>
<v-text-field
v-model="password"
:type="showPassword ? 'text' : 'password'"
label="Password"
prepend-icon="mdi-lock"
:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
#click:append="showPassword = !showPassword"
#blur="$v.password.$touch()"
/>
<div
class="red--text text--lighten-1"
v-if="$v.password.$error && !$v.password.required"
>
<v-icon color="red">mdi-alert-circle-outline</v-icon>
Password is required
</div>
<v-btn
type="submit"
color="success"
name="button"
:disabled="$v.$invalid"
>
Login now
</v-btn>
<v-btn
text
small
color="primary"
:to="{ name: 'forgotPassword' }"
>
Forgot your password?
</v-btn>
<div v-if="error" class="red--text text--lighten-1">
<v-icon color="red">mdi-alert-circle-outline</v-icon>
{{ getLoginErrorMsg() }}
</div>
</v-form>
</v-card-text>
</v-card>
</v-flex>
</v-layout>
</v-container>
</template>
<script>
import { required, email } from "vuelidate/lib/validators";
export default {
name: "Login",
data() {
return {
email: "",
password: "",
error: null,
showPassword: false
};
},
validations: {
email: {
required,
email
},
password: {
required
}
},
methods: {
login() {
console.log("Entering component login method");
this.$store
.dispatch("user/login", {
username: this.email,
password: this.password
})
.then(() => {
console.log(
'this.$store.getters["user/passwordChangeRequired"]' +
this.$store.getters["user/passwordChangeRequired"]
);
if (this.$store.getters["user/passwordChangeRequired"]) {
console.log("push to changePassword");
this.$router.push({ name: "changePassword" });
} else {
console.log("pushing to home");
this.$router.push({ name: "home" });
}
})
.catch(err => {
this.error = err.response;
});
},
getLoginErrorMsg() {
if (this.error.status == 401) {
return "Invalid username or password";
} else {
// return `Login failed: {this.error.statusText}`;
return "failed";
}
}
}
};
</script>
<style></style>
Here is the test file:
import { expect } from "chai";
import { mount, shallowMount } from "#vue/test-utils";
import Login from "../../src/views/user/Login.vue";
describe("Login", () => {
it("Has login text", () => {
// const wrapper = mount(Login);
const wrapper = shallowMount(Login);
// not getting here.
expect(2).to.equal(2);
});
});
Note: neither mount or shallowMount works. They both throw the same error.
Here is my webpack.config.js file:
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
// this will apply to both plain `.js` files
// AND `<script>` blocks in `.vue` files
{
test: /\.js$/,
loader: 'babel-loader'
},
// this will apply to both plain `.css` files
// AND `<style>` blocks in `.vue` files
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
}
]
},
plugins: [
// make sure to include the plugin for the magic
new VueLoaderPlugin()
]
}
I've spent hours googling and I can't really find anything. So, I'm clearly doing something really stupid, because no one else seems to be having this issue. Please tell me why it is throwing this error and unable to shallowMount or mount this vue component.
It appears that my tests/unit/index.js was missing some things... I didn't have vuelidate in there and I believe that was the issue. I changed it to the following and it now works:
// index.js
import Vue from 'vue';
import Vuetify from 'vuetify';
import VueRouter from 'vue-router';
import Vuelidate from "vuelidate";
Vue.config.productionTip = false;
Vue.use(Vuetify);
Vue.use(VueRouter);
Vue.use(Vuelidate);

How to include images with html-webpack-plugin + twig-loader?

I'm trying to include an image in my twig template just like simple tag, but it doesn't want to include. For build, I use HtmlWebpackPlugin and twig-loader;
But if I do the same with html-loader and html template - it works fine.
How to do it right with twig-loader?
my webpack-config:
const path = require( 'path' );
const HtmlWebpackPlugin = require( 'html-webpack-plugin' );
const PATHS = {
source: path.join( __dirname, './source' ),
build: path.join( __dirname, './build' )
};
module.exports = {
entry: `${ PATHS.source }/index.js`,
output: {
path: PATHS.build,
filename: 'webpack.bundle.js'
},
module: {
rules: [
{
test: /\.twig/,
loader: 'twig-loader'
},
{
test: /.*\.(gif|png|jpe?g)$/i,
use: [
{
loader: 'file-loader?name=[name].[ext]'
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin( {
filename: 'index.html',
template: `${PATHS.source}/index.twig`,
} )
],
};
my twig template:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<img src="./chuck-norris.jpg" alt="">
</body>
</html>
my package.json:
{
"name": "htmlWebpackPlugin-twigLoader",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"author": "evisotskiy",
"license": "ISC",
"devDependencies": {
"file-loader": "^0.11.2",
"html-loader": "^0.5.1",
"html-webpack-plugin": "^2.30.1",
"twig-loader": "^0.3.1",
"webpack": "^3.6.0"
}
}
my project's structure:
.
├── webpack.config.js
├── package.json
├── source
| ├──index.twig
| ├──index.js (empty)
| ├──chuck-norris.jpg
and when I execute npm run build I get dir:
├── build
| ├──index.html
| ├──webpack.bundle.js
without chuck-norris.jpg
And when I use html-loader instead twig-loader and html-template instead twig-template - image builds fine. But for my project, I need to use twig templates.
How to do it right with twig-loader?
I have found a solution. Instead of passing to HtmlWebpackPlugin as template the .twig-file directly, I passed as template a .js-file, inside of which I included a .twig file and image, and passed the image to the twig-template as a variable. Now the project looks like this:
my webpack-config:
const path = require( 'path' );
const HtmlWebpackPlugin = require( 'html-webpack-plugin' );
const PATHS = {
source: path.join( __dirname, './source' ),
build: path.join( __dirname, './build' )
};
module.exports = {
entry: `${ PATHS.source }/index.js`,
output: {
path: PATHS.build,
filename: 'webpack.bundle.js'
},
module: {
rules: [
{
test: /\.twig$/,
loader: 'twig-loader'
},
{
test: /.*\.(gif|png|jpe?g)$/i,
use: [
{
loader: 'file-loader?name=[name].[ext]'
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin( {
filename: 'index.html',
template: `${PATHS.source}/index.twig.js`,
} )
],
};
my twig template:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<img src="{{ image.src }}" alt="{{ image.alt }}">
</body>
</html>
my index.twig.js:
const template = require( './index.twig' );
const image = {
src: require( './chuck-norris.jpg' ),
alt: "Chuck Norris"
};
module.exports = template( { image } );
my package.json:
{
"name": "htmlWebpackPlugin-twigLoader",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"author": "evisotskiy",
"license": "ISC",
"devDependencies": {
"file-loader": "^0.11.2",
"html-webpack-plugin": "^2.30.1",
"twig-loader": "^0.3.1",
"webpack": "^3.6.0"
}
}
my project's structure:
.
├── webpack.config.js
├── package.json
├── source
| ├──index.twig
| ├──index.twig.js
| ├──index.js (empty)
| ├──chuck-norris.jpg
and when I execute npm run build I get builded project I expected:
├── build
| ├──index.html
| ├──chuck-norris.jpg
| ├──webpack.bundle.js
I faced the same problem recently. But I could not use a solution with handling URLs as parameters.
I've fixed it with extract-loader and html-loader.
Honestly, I don't know how it works, but it works.
This is a task for gulp.
See rules with test: /\.(jpeg|png|svg|jpg|gif)$/i, and test: /\.twig$/,
//region js
task('app:compile', function(){
return src(path.js.src)
.pipe(named())
.pipe(webpack({
mode: 'development',
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
plugins: ['#babel/plugin-proposal-object-rest-spread']
}
}
},
{
test: /\.(scss|css)$/,
exclude: /(node_modules|bower_components)/,
use: [
{loader: "style-loader"},
{loader: "css-loader"},
{loader: "sass-loader"},
],
},
{
test: /\.(jpeg|png|svg|jpg|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: '../images',
publicPath: 'images',
}
},
],
},
{
test: /\.twig$/,
use: [
'twig-loader',
'extract-loader',
{
loader:'html-loader',
},
],
},
{
test:/\.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: '../fonts',
publicPath: 'fonts',
}
},
],
},
],
},
devtool: 'source-map',
}))
.pipe(dest(path.js.dest));
});
//endregion
You can see the full version of gulpfile.js at the link
landing_scratch gulpfile.js
Hope it helps somebody who is googling the same questions.
If it's any help, I fixed this very same problem by simply changing the loader that processes the twig template files and adding "html-loader".
This would be the change:
{
test: /\.twig$/,
loader: 'twig-loader'
}
to
{
test: /\.twig$/,
exclude: /node_modules/,
use: [
'html-loader',
'twig-html-loader'
]
}
Of course, you must install those loaders previously if you didn't do it yet.
npm install twig-html-loader html-loader --save-dev
Henceforth, the images will be processed ;)
I incorporated Twig templates in my advanced SPA build with Vue CLI. The issue I faced was the same as the topic starter.
My Twig templates were compiled fine. But the images in the templates were not copied to build folder. And the paths in resulting output HTML files were not transformed into their Webpack-built-and-hashed paths.
At the same time the images in .vue files were copied and the images paths were updated.
To solve this I applied the core of the solution from #s.smsmsm above to my context. Thanks mate.
Briefly: you have to make Webpack to use 3 loaders to process your Twig templates. These are twig-loader, extract-loader and html-loader.
For this I made the specifig vue.config.js.
See it here with more explanations. The short version follows.
// vue.config.js
module.exports = {
runtimeCompiler: true,
outputDir: '.dist',
pages: {
main: {
entry: 'src/js/main.js',
template: 'src/views/pages/index.twig',
filename: 'index.html'
}
},
// Here is where the fix actually is made.
chainWebpack: config => {
config.module
.rule('twig')
.test(/\.twig$/)
.use('twig-loader')
.loader('twig-loader')
.end()
.use('extract-loader')
.loader('extract-loader')
.end()
.use('html-loader')
.loader('html-loader')
.end();
}
};
The Vue CLI config reference is here. Its chainWebpack option was used to modify the respective Webpack config part via vue.config.js. How to add a new loader doc is here.

Unit Testing of Angular 2 Component using Jasmine

I am trying to unit test the Angular 2 Component using Jasmine. My Component is as follows
import { Component } from '#angular/core';
import {Employee} from './Employee';
#Component({
selector: 'emp-data',
templateUrl: './app/app.html'
})
export class EmployeeComponent {
emp:Employee;
private name: string = 'John';
constructor() {
this.emp =new Employee();
}
getTax():number{
console.log('sal' + this.emp.salary + ' desig ' + this.emp.designation);
if(this.emp.designation=='Manager'){
this.emp.tax = this.emp.salary*0.3;
}
if(this.emp.designation=='Lead'){
this.emp.tax = this.emp.salary*0.25;
}
console.log("Tax " + this.emp.tax);
return this.emp.tax;
}
printMessage():string{
return `Hello ${this.name}`;
};
}
The Spec file is as follows
import {EmployeeComponent} from './appcomponent';
describe('EmployeeComponent',()=>{
beforeEach(()=>{
this.app = new EmployeeComponent();
});
it('should have name property', function() {
expect(this.app.name).toBe('Mahesh');
});
it('should say hello with name property', function() {
expect(this.app.printMessage()).toBe('Hello Mahesh');
});
});
The Tester.html file is as follows
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>Ng App Unit Tests</title>
<link rel="stylesheet" href="../node_modules/jasmine-core/lib/jasmine-core/jasmine.css">
<script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script>
<script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
<script src="../node_modules/jasmine-core/lib/jasmine-core/boot.js"></script>
<script src="../node_modules/es6-shim/es6-shim.min.js"></script>
<script src="../node_modules/systemjs/dist/system-polyfills.js"></script>
<script src="../node_modules/es6-shim/es6-shim.min.js"></script>
<script src="../node_modules/reflect-metadata/Reflect.js"></script>
<script src="../node_modules/zone.js/dist/zone.js"></script>
<script src="../node_modules/#angular/core/testing/testing.js"></script>
<script src="systemjs.config.js"></script>
<script src="../app/appcomponent.js"></script>
<script src="../app/component.spec.js"></script>
</head>
<body>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script>
System.config({
packages: {
'app': {defaultExtension: 'js'}
}
});
System.import('app/component.spec')
.then(window.onload)
.catch(console.error.bind(console));
</script>
</body>
</html>
The Package.json is as follows
{
"name": "ng2-component-testing",
"version": "1.0.0",
"scripts": {
"start": "concurrently \"tsc -w\" \"node server.js\"",
"tsc": "tsc",
"tsc:w": "tsc -w",
"lite": "lite-server",
"typings": "typings",
"postinstall": "typings install",
"testLite": "live-server --open=unit-tests.html",
"lite-server-test": "lite-server --config=liteserver-test-config.json",
"test": "tsc && concurrently \"npm run tsc:w\" \"npm run lite-server-test\" "
},
"license": "ISC",
"dependencies": {
"#angular/common": "2.0.0-rc.1",
"#angular/compiler": "2.0.0-rc.1",
"#angular/core": "2.0.0-rc.1",
"#angular/http": "2.0.0-rc.1",
"#angular/platform-browser": "2.0.0-rc.1",
"#angular/platform-browser-dynamic": "2.0.0-rc.1",
"#angular/router": "3.0.0-alpha.3",
"bootstrap": "^3.3.6",
"es6-shim": "^0.35.1",
"jasmine-core": "~2.4.1",
"koa": "^1.2.0",
"koa-static": "^2.0.0",
"livereload": "^0.4.1",
"reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.6",
"systemjs": "^0.19.24",
"zone.js": "0.6.6"
},
"devDependencies": {
"concurrently": "^2.0.0",
"jasmine-core": "2.4.1",
"lite-server": "^2.1.0",
"node-gyp": "^3.3.1",
"typescript": "^1.8.7",
"typings": "^0.7.5"
}
}
When I run the test, the following result is displayed
The following error messages are displayed in Console of the browser
I have tries various solutions on Stackoverflow but not successful in it.
So can anybody help me on this?
Thanks in advance.