I have created a javascript library with webpack, that outputs a systemjs module. This module has a dependency on react, which I specified as an external.
The resulting javascript file starts like this:
System.register(["react"], function(__WEBPACK_DYNAMIC_EXPORT__) {
var __WEBPACK_EXTERNAL_MODULE_react__;
return { ....
Additionally I have an app, that uses SystemJS during runtime to load that module. In order to provide the react dependency, I have defined an importmap:
{
"imports": {
"react": "https://unpkg.com/react#16.11.0/umd/react.production.min.js"
}
}
And the part, where I import the module, looks like this:
const modulePromise = System.import(MODULE_URL);
modulePromise.then(module => {
console.log('module loaded successfully!');
});
The problem now is, that the console.log is never called, because I get a TypeError, that says, that "Component is not a property of undefined", which tells me, that somehow react has not correctly been passed to my module.
To be precise, in the browser network tab I see, that my module and the react import is indeed loaded, but somehow it is not correctly processed.
Has anyone an idea, what i might be doing wrong?
OK, so eventually I solved this myself, although a bit different.
First, I did not use the unpkg link anymore, but I actually include React as a library in my main app.
And I changed my importmap to:
<script type="systemjs-importmap">
{
"imports": {
"react": "app:react",
"react-dom": "app:react-dom"
}
}
</script>
Also in the main app I use System.set(...) from SystemJs to tell SystemJS where to find the 'app:react' and 'app:react-dom' dependencies:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import 'systemjs/dist/system.min';
...
System.set('app:react', { default: React, __useDefault: true });
System.set('app:react-dom', { default: ReactDOM, __useDefault: true });
And now, if I load my module with that external react dependency through SystemJS, it works.
Related
I am trying to import an npm package into a Vue component.
The package (JSPrintManager - here) is just a JavaScript file with no exports. Consequently, I cannot use:
import { JSPM } from "jsprintmanager"
I have also had no success with the following:
import JSPM from "jsprintmanager"
import * as JSPM from "../../node_modules/jsprintmanager/JSPrintManager"
import * as JSPM from "../../node_modules/jsprintmanager/JSPrintManager.js"
Am I barking up the wrong tree?
If there is no way to import an npm package that is not a module, is there another way to load the relevant JavaScript file (currently residing in my node-modules directory) into my component?
I am using the Vue CLI
jspm.plugin.js
import * from '../../node_modules/jsprintmanager/JSPrintManager';
export default {
install(Vue) {
Vue.prototype.$JSPM = window.JSPM
}
}
main.js
import Vue from 'vue'
import JSPM from './jspm.plugin';
Vue.use(JSPM);
In any of your components you can now access JSPM as this.$JSPM
If you want to use it outside of your components (say, in store) and you want it to be the same instance as the one Vue uses, export it from Vue, in main.js
const Instance = new Vue({
...whatever you have here..
}).$mount('#app');
export const { $JSPM } = Instance
Now you can import { $JSPM } from '#/main' anywhere.
That would be the Vue way. Now, in all fairness, the fact your import is run for the side effect of attaching something to the window object which you then inject into Vue is not very Vue-ish. So the quick and dirty way to do it would be, in your component:
import * from '../../node_modules/jsprintmanager/JSPrintManager';
export default {
data: () => ({
JSPM: null
}),
mounted() {
this.JSPM = window.JSPM;
// this.JSPM is available in any of your methods
// after mount, obviously
}
}
The main point of the above "simpler" method is that you have to make the assignment after the page finished loading and running the JSPM code (and window.JSPM has been populated).
Obviously, if you disover it sometimes fails (due to size, poor connection or poor hosting), you might want to check window.JSPM for truthiness and, if not there yet, call the assignment function again after in a few seconds until it succeeds or until it reaches the max number of tries you set for it.
In relation to a previous question - How can Enzyme check for component visibility? I tried using jest-dom to specifically use their toBeVisible function.
Despite following the documentation I cannot get it to work in my test and get the error
"TypeError: expect(...).not.toBeVisible is not a function"
Fully reproduced in CodeSandbox here
import Enzyme, { mount } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import React from "react";
import MyCheckbox from "./MyCheckbox";
import MyCheckboxesInUse from "./MyCheckboxesInUse";
Enzyme.configure({ adapter: new Adapter() });
test("Check that one checkbox is hidden and the other is visible", () => {
const wrapper = mount(<MyCheckboxesInUse />);
const checkboxes = wrapper.find(MyCheckbox);
expect(checkboxes).toHaveLength(2);
//HOW DO I CHECK THAT ONE IS VISIBLE AND THE OTHER IS NOT ?
expect(checkboxes.get(0)).not.toBeVisible();
expect(checkboxes.get(1)).toBeVisible();
});
I was facing a similar issue. In my case, it was resolved by the following steps:-
Adding the #testing-library/jest-dom package to the devDependencies instead of dependencies in the package.json file.
Next add one of the following:
Adding import '#testing-library/jest-dom'; to the setupTests.js
Or adding in jest configuration (package.json): "setupFilesAfterEnv": [ "#testing-library/jest-dom/extend-expect" ]
The expect().not.toBeVisible method comes from the #testing-library/jest-dom library, since there is no setup or reference to that library the default jest expect is used (thus the function is not found). A quick fix would be to add this import to the top of your test file (assuming you have already imported the library into your project via npm or yarn):
import '#testing-library/jest-dom';
For scalability you may want to add a setupTest.js file (reference here: https://create-react-app.dev/docs/running-tests/)
importing '#testing-library/jest-dom' doesn't help me but
importing #testing-library/jest-dom/extend-expect' help me resolve the error.
import '#testing-library/jest-dom/extend-expect'
I´m trying to create a form. This form have a package.json with vue, axios and sweetalert.
"dependencies": {
"axios": "^0.19.0",
"vue": "^2.6.10",
"vue-sweetalert2": "^2.1.1"
}
The JS is
<script>
import Vue from 'vue';
import VueSweetalert2 from 'vue-sweetalert2';
import VueAxios from 'vue-axios';
import axios from 'axios';
import 'sweetalert2/dist/sweetalert2.min.css';
Vue.use(VueSweetalert2, VueAxios, axios);
var app = new Vue({
el: '#app',
methods: {
guardar: function () {
axios
.get('ENDPONT')
.then(response => {
console.log(response);
Vue.swal('Hello Vue world!!!');
})
.catch(function (error) {
console.log(error);
Vue.swal('Hello Vue world!!!');
});
}
}
});
</script>
The error is simple: Return 'Cannot use import statement outside a module'. I suppose that import is wrong, but im new in Vue and don't know what is the right way.
You're trying to use an import statement in a normal script tag, you can only do that with type="module" but I suspect you will run into many other issues if you continue down this path as many libraries are not built for use with ESM modules yet.
You'll be better off generating a project with https://cli.vuejs.org/ which will create a good starting base and compile your code and put it in a /build folder for you to deploy to your web hosting.
Hello encountered the same issue in laravel 9 with vue3 js and vite
the solution you have to configure your .env
because when you run => npm run build, it create the build folder where your js, images , css will be compile, those files will be used in your App
Go in .env and Add this code: ASSET_URL=http://localhost/public
Now if you run build, all object will be prefix by //localhost/public
=>Ex. http://localhost/public/build/js/app1332527.js
require('__path_to_vue.js__')
If you intend to use it outside module
I removed defer from
<script src="{{ asset('js/app.js') }}" defer></script>
and it worked perfectly
I am trying to manually include the #material/drawer npm package into my Ember app. I tried following this guide but I'm running into some weird errors in my Chrome dev console:
Uncaught SyntaxError: Unexpected token *
Uncaught ReferenceError: define is not defined
The first is from the imported node_modules/#material/drawer/index.js file and the second is from my generated shim.
My component code:
import Component from '#ember/component';
import { MDCTemporaryDrawer, MDCTemporaryDrawerFoundation, util } from '#material/drawer';
export default Component.extend({
init() {
this._super(...arguments);
const drawer = new MDCTemporaryDrawer(document.querySelector('.mdc-drawer--temporary'));
document.querySelector('.menu').addEventListener('click', () => drawer.open = true);
}
});
In my ember-cli-build.js:
app.import('node_modules/#material/drawer/index.js');
app.import('vendor/shims/#material/drawer.js');
My generated shim:
(function() {
function vendorModule() {
'use strict';
return {
'default': self['#material/drawer'],
__esModule: true,
};
}
define('#material/drawer', [], vendorModule);
})();
What exactly am I doing wrong? It almost seems as though raw ES6 code got imported rather than compiled into my JS build output.
I also read this SO post but there are too many answers and I'm not sure which to do. It seems this specific answer is what I'm trying to do but not verbatim enough.
Creating a shim only ensures that ember-cli gets an AMD module, which you then can import in your app files.
If the npm package needs a build or transpiling step beforhand, this won't work.
You need a way to get the package build within the ember-cli build pipeline.
Luckily there are addons which can take care of this for you: ember-auto-import and ember-cli-cjs-transform.
You may have also heard of ember-browserify, which does the same thing, but it's deprectaed in favor of ember-auto-import.
I'd suggest you try ember-auto-import:
ember install ember-auto-import
You then should be able to import as you tried:
import { MDCTemporaryDrawer, MDCTemporaryDrawerFoundation, util } from '#material/drawer';
No shim or app.import needed, as ember-auto-import will take care of this for you.
I am working on a project that requires using a js plugin. Now that we're using vue and we have a component to handle the plugin based logic, I need to import the js plugin file within the vue component in order to initialize the plugin.
Previously, this was handled within the markup as follows:
<script src="//api.myplugincom/widget/mykey.js
"></script>
This is what I tried, but I am getting a compile time error:
MyComponent.vue
import Vue from 'vue';
import * from '//api.myplugincom/widget/mykey.js';
export default {
data: {
My question is, what is the proper way to import this javascript file so I can use it within my vue component?
...
Include an external JavaScript file
Try including your (external) JavaScript into the mounted hook of your Vue component.
<script>
export default {
mounted() {
const plugin = document.createElement("script");
plugin.setAttribute(
"src",
"//api.myplugincom/widget/mykey.js"
);
plugin.async = true;
document.head.appendChild(plugin);
}
};
</script>
Reference: How to include a tag on a Vue component
Import a local JavaScript file
In the case that you would like to import a local JavaScript in your Vue component, you can import it this way:
MyComponent.vue
<script>
import * as mykey from '../assets/js/mykey.js'
export default {
data() {
return {
message: `Hello ${mykey.MY_CONST}!` // Hello Vue.js!
}
}
}
</script>
Suppose your project structure looks like:
src
- assets
- js
- mykey.js
- components
MyComponent.vue
And you can export variables or functions in mykey.js:
export let myVariable = {};
export const MY_CONST = 'Vue.js';
export function myFoo(a, b) {
return a + b;
}
Note: checked with Vue.js version 2.6.10
try to download this script
import * from '{path}/mykey.js'.
or import script
<script src="//api.myplugincom/widget/mykey.js"></script>
in <head>, use global variable in your component.
For scripts you bring in the browser way (i.e., with tags), they generally make some variable available globally.
For these, you don't have to import anything. They'll just be available.
If you are using something like Webstorm (or any of the related JetBrains IDEs), you can add /* global globalValueHere */ to let it know that "hey, this isn't defined in my file, but it exists." It isn't required, but it'll make the "undefined" squiggly lines go away.
For example:
/* global Vue */
is what I use when I am pulling Vue down from a CDN (instead of using it directly).
Beyond that, you just use it as you normally would.
I wanted to embed a script on my component and tried everything mentioned above, but the script contains document.write. Then I found a short article on Medium about using postscribe which was an easy fix and resolved the matter.
npm i postscribe --save
Then I was able to go from there. I disabled the useless escape from eslint and used #gist as the template's single root element id:
import postscribe from 'postscribe';
export default {
name: "MyTemplate",
mounted: function() {
postscribe(
"#gist",
/* eslint-disable-next-line */
`<script src='...'><\/script>`
);
},
The article is here for reference:
https://medium.com/#gaute.meek/how-to-add-a-script-tag-in-a-vue-component-34f57b2fe9bd
For anyone including an external JS file and having trouble accessing the jQuery prototype method(s) inside of the loaded script.
Sample projects I saw in vanilla JS, React and Angular were simply using:
$("#someId").somePlugin(options)
or
window.$("#someId").somePlugin(options)
But when I try either of those in my VueJS component I receive:
Error: _webpack_provided_window_dot$(...).somePluginis not a function
I examined the window object after the resources had loaded I was able to find the jQuery prototype method in the window.self read-only property that returns the window itself:
window.self.$("#someId").somePlugin(options)
Many examples show how to load the external JS file in VueJS but not actually using the jQuery prototype methods within the component.