Webpack loads unwanted file when passing string+variable to require() - javascript

When running the following code I get an error when building with Webpack:
const name = 'Test';
const test = require(`./app/model/${name}`);
However, with the following code I get no error:
const test = require('./app/model/Test');
The error received is:
ERROR in ./node_modules/express/lib/request.js
Module not found: Error: Can't resolve 'net' in '/path/to/maestro/node_modules/express/lib'
# ./node_modules/express/lib/request.js 18:11-25
# ./node_modules/express/lib/express.js
# ./node_modules/express/index.js
# ./app/model/CommanderProgram.js
# ./app/model sync ^\.\/.*$
# ./web.js
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! xops-pat#4.0.0-rc1 build: `webpack`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the xops-pat#4.0.0-rc1 build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /path/to/error/log/2019-12-09T16_19_45_494Z-debug.log
The contents of ./app/model/Test.js are:
'use strict';
module.exports = 'asdf';
So no dependencies. The error above mentions ./app/model/CommanderProgram.js, which absolutely should not be Webpack'd. Based on the fact that Test.js has nothing in it, Webpack should not be trying to include CommanderProgram.js, though. However, if I delete CommanderProgram.js then the error does NOT occur. Restoring CommanderProgram.js then renaming it to either AAA.js or ZZZ.js still DOES cause the problem (without updating references, so nothing could be importing AAA.js/ZZZ.js), so somehow Webpack is trying to include an un-referenced file.
I also tried the following, showing it's not an issue with template literals:
const name = 'Test';
const test = require('./app/model/' + name);
Why does Webpack appear to include an un-referenced file when using variables in strings passed to require?
Environment:
Node: v10.16.3
OS: Windows 10
Webpack: 4.41.2
Webpack-cli: 3.3.10
See code here: https://github.com/xOPERATIONS/maestro/blob/9d7977f52c1a08bc947666f3b1c85c30787cb831/web.js

The underlying problem is documented here: https://webpack.js.org/guides/dependency-management/#require-with-expression
In short, doing require('./app/model/' + name) makes Webpack include files in the directory ./app/model matching regular expressing .* (i.e. everything in that directory). So while CommanderProgram.js was the module that caused errors, thus making this a problem, all other modules in that directory were also being included even if they were not desired.
EDIT: Replacing the string+variable with a function expression in this case will prevent the undesired file from being loaded, and thus the error will go away. However, using a function expression will NOT solve the problem of trying to load modules using variables.
Original answer (does not work):
To get around this, do one of the following (which all boil down to "wrap the string in a function"):
Construct an absolute path with path.resolve():
const test = require(path.resolve(__dirname, 'app/model', name));
Construct the require-string with a function:
const myfunc = function(mod) {
return `./app/model/${mod}`;
};
const name = 'Test';
const test = require(myfunc(name));
Construct the require-string with an IEFE (immediately envoking function expression):
const test = require(
(function() {
return `./app/model/${name}`;
}())
);

Related

Jest not recognising JQuery Object ($)

I have used JavaScript to created a simple web application to measure how much time I spend on different projects.
I want to test the code with Jest and this works fine until I try to test a function that contains the JQuery object ($).
This is the error message I get:
ReferenceError: $ is not defined
The answers I have found online tells me that I need to add a jQuery dependency in my global object, which I have done. Below is my package.json file:
"jest": {
"setupFiles": ["PathToSetupFile/setup-jest.js"],
"type": "module"
and my setup-jest.js:
import $ from 'jquery';
global.$ = global.jQuery = $;
I am now met with a new error message:
SyntaxError: Cannot use import statement outside a module
I cannot find any further information on how to fix this. A few resources tell me I need to update my jest.config.js file but this file does not exist anywhere in my node modules.
I thought it would be helpful to start completely from the beginning and therefore address a much wider scope but never the less provide the exact answer to your problem at the end of my response here.
In PowerShell CD to your project folder
Install the jest node modules locally into your project folder using
npm install --save-dev jest
Install jest globally so you can use it as a CLI command
npm install jest -g
This installs Jest globally i.e. to your user profile %APPDATA%\npm location
Ensure %APPDATA%\npm is in your user profile environment PATH variable (in Windows settings, "Edit Environment variables for your account")
Check in your PowerShell console that it is in your path using $Env:PATH. (If your %APPDATA%\npm path still isn't showing then restart the PowerShell window, if the terminal is inside VSCode then you will have to restart VSCode so that the terminal inherits the new environment)
In order to import jquery you will need to a) install jquery and b) define a setup file for jest which is referenced in jest.config.js created using jest --init in your project folder.
Install jquery -
npm install --save-dev jquery
Generate jest.config.js -
jest --init
The following questions will help Jest to create a suitable configuration for your project
√ Would you like to use Typescript for the configuration file? ... no
√ Choose the test environment that will be used for testing » jsdom (browser-like)
√ Do you want Jest to add coverage reports? ... yes
√ Which provider should be used to instrument code for coverage? » v8
√ Automatically clear mock calls, instances, contexts and results before every test? ... yes
✏️ Modified your\project\folder\package.json
📝 Configuration file created at jest.config.js
If you don't specify the jsdom (browser-like) test environment then running code under test that uses jquery will yield an error of "jQuery requires a window with a document"
But this means the 'jest-environment-jsdom' must now be installed
(As of Jest 28 "jest-environment-jsdom" is no longer shipped by default, make sure to install it separately.) -
npm install --save-dev jest-environment-jsdom
Edit jest.config.js
Change
// setupFiles: [],
To
setupFiles: [ './jest.setup.js' ],
N.B. the "./" prefix is required otherwise jest will state it cannot find the jest.setup.js file.
The create jest.setup.js in your project folder and add the following -
const $ = require('jquery');
global.$ = global.jQuery = $;
Node uses the CommonJS module system (https://nodejs.org/en/knowledge/getting-started/what-is-require/)
so the above syntax is required to work with Node.js

"ERROR in xx.js from UglifyJs Invalid assignment" when importing a module into another module

I cannot post exact code due to NDAs, so I will do my best.
Javascript is not my string suit, but I took it up for my team.
Background:
I built a module which basically will perform a very simple task and can be imported as a dependency in other projects and then added into the project by adding the tag.
I wanted to keep this as lightweight as possible and let the app which was adding it in do the heavy lifting and have the imports to run and compile Angular code.
Code for SimpleApp:
Everything seems to work fine except for places marked with /* Potential Issue */
Within the simple module, I have a few file:
simpleApp.js -- the main js file which does the work necessary
simpleApp.html -- the html of simpleApp.js
innerProvider.js -- a module.service which does some work when called from the simpleApp.js -- this import seems to be the issue causer.
All within the companySimpleApp package:
simpleApp.js:
import angular from "angular"
/* I believe this to be the issue */
import innerProviderModule from "./pathToFile/innerProvider /* Potential Issue */
/* Potential Issue */
angular.module('simpleApp', [innerProviderModule]).component('simpleComponent, {
controller: ['$scope, 'innerProvider', ..., function($scope, innerProvider, ...) {
/* does work */
}],
template: require("./simpleApp.html"),
bindings: {
bind1: '#',
bind2: '#'
}
simpleApp.html:
<div>
do stuff
call stuff
</div>
innerProvider.js:
import angular from "angular"
const innerProviderModule = angular.module('innerProvider', [])
.service('innerProvider', function (%http, ...) {
this.doWork = function (param1) {
retStmt = doSomething(param1)
return retStmt
}
});
export default innerProviderModule.name;
Everything here builds correctly and will do as is told. I am able to build this package as well as the one which uses it and have a working webpage with the simpleApp's services. However, this is when I host everything myself.
Code for Larger Service using SimpleApp:
In another project I have this listed as a dependency "simpleApp = 1.0" this may be different than expected due to my company's internal workings, but this works.
It appears in the node_module directory
I then have a module for the webpage which loads in simpleApp and has all of the other packages like angular, babel, uglify, webpack, etc:
/* Potential Issue */
import "companySimpleApp/simpleApp.js"
export default angular
.module("app", [otherDependencies, simpleApp])
.config(function ($stateProvider, $stuff){
someMappingsForUrls
});
...
<script src="../node_modules/companySimpleApp/simpleApp.js"></script>
...
and another html and js file which use the simpleApp
<div>
<simpleApp bind1='{{value}}'></simpleApp>
</div>
Error:
Now, everything will run fine on my localhost and I can fully use the larger service using SimpleApp site with the simpleApp. However, when I build this (npm run webpack) on the service using simpleApp, I get the following error even though everything seems to run fine on my localhost:
ERROR in bundle.js from UglifyJs
Invalid assignment [bundle.js:146461,67]
npm ERR! code ELIFECYCLE
npm ERR! errno 2
npm ERR! # webpack: `webpack -p`
npm ERR! Exit status 2
npm ERR!
npm ERR! Failed at the # webpack script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
........
The code seems to build when I remove the import innerProviderModule from "./pathToFile/innerProvider from simpleApp.js but I then get an error saying that innerProvider is an unresolved reference or something along the line.
What I am asking is for some help on why I may be seeing this error when I import the innerProviderModule I built. Do I need to add webpack and all that to my simpleApp project even though it all seems to run fine physically on my localhost?
Any help or ideas is very much so appreciated. Thanks!
Bumping this as I posted it late at night.
Edit: It seems to not like "=>" in the innerProvider which I have
I built the package which uses the simpleApp with 'webpack -p' which was not done on simpleApp. So, what it looked like that happened was that the simpleApp was not minified or something and didnt like a few lines in the provider code (ie: "=>", "let", etc...)
So instead of having the simpleApp have more dependencies, I simply wrote code which would pass webpack -p.
You should also be able to just remove the "-p" flag
Hope this helps someone.

Expecting end of input, "ADD", "SUB", "MUL", "DIV", got unexpected "RPAREN"

I work with Augmented UI in my Gatsby project, every thing works great in dev mode.
When I go with build command, I got this log error:
info bootstrap finished - 4.630 s
⠀
failed Building production JavaScript and CSS bundles - 9.761s
ERROR #98123 WEBPACK
Generating JavaScript bundles failed
Parse error on line 1:
...n-x, calc(var(--aug-_TlJoinRX, 0px)/2 + var(--aug-_TrJoinLX, 100%)/2)) + var(--...
------------------------------------------------------------------------^
Expecting end of input, "ADD", "SUB", "MUL", "DIV", got unexpected "RPAREN"
not finished run queries - 9.857s
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! project#1.0.0 build: `gatsby build`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the project#1.0.0 build script.
After some researches, it seems that PostCSS is unable to work along with Augmented UI (on calc functions).
I'm unable to find a way to disable PostCSS on this.
My dependencies versions are:
"gatsby": "^2.18.5",
"gatsby-plugin-postcss": "^2.1.16"
My current postcss.config.js looks like that:
module.exports = () => ({
plugins: [require('tailwindcss')],
})
Thanks for any help on this subject.
#Zooly, the problem is related with the use of calc function in the CSS preprocessor or minifier. From the Augmented UI's documentation:
Compatibility with Create React App (And in my situation, Vue)
Create React App depends on PostCSS and cssnano. Both of these libraries have parsing bugs that block augmented-ui so you'll need to copy augmented-ui.min.css into the public folder and manually include it in the index.html file to avoid them until they're fixed.
https://augmented-ui.com/docs/#install
As you can see at this support answer on GitHub https://github.com/propjockey/augmented-ui/issues/3#issuecomment-579671714, you can add this key to your package.json config file:
"cssnano": {
"preset": [
"default",
{
"calc": false
}
]
},
I use this workaround and it works fine to build my Vue project. Hope it works for yours too.
I ran into the same problem (also with Argument UI), and did not fix it. But here is a quick work around:
<Helmet>
<link rel='stylesheet' href='https://unpkg.com/augmented-ui/augmented.css' />
</Helmet>
And just a heads up: I had to delete my public and .cache folder to get the build to include the link to the CDN.

CoffeeScript Cakefile not finding NPM Module node-glob

I am trying to use a code snippet from a README for node-glob in CoffeeScript. I installed the package:
npm install --global glob
I am trying to use the following snippet:
var glob = require("glob")
// options is optional
glob("**/*.js", options, function (er, files) {
// files is an array of filenames.
// If the `nonull` option is set, and nothing
// was found, then files is ["**/*.js"]
// er is an error object or null.
})
and I assume its then written something similar to this in CoffeeScript:
# Cakefile
{glob} = require 'glob' # npm install --global glob
task 'glob-test', 'Testing Globs', ->
glob.sync("**/*.ts") (er, files) ->
console.log files
However, I get the following error messages:
Error: Cannot find module 'glob'
Am I doing this correctly, or is it even possible CoffeeScript and I should just abandon the whole idea?
UPDATE:
Installed the node-glob module as a locally vendored module this time using:
npm install glob
and changed {glob} to glob in the require statement.
and ran the Cakefile task again. Got this error this time.

Running Jasmine Tests from Grunt on JavaScript that uses Require

I am writing some extensions to lodash. The code related to this question can be download from here. The structure is that code is located in /shared/modules/myExtensions.js. Currently, my code is very basic and looks like this:
'use strict';
var _ = require('lodash');
_.mixin({
'myFunction' : function(s) {
return 'Hello ' + s;
}
});
module.exports = _;
My code will grow in complexity. For that reason, I want to setup unit tests from the start on this. Right now, my tests are located at /shared/tests/myExtensions.tests.js. That file looks like this:
'use strict';
describe('myModule', function() {
it('should work', function() {
expect(true).toBe(true);
});
});
This test always asserts to true. I'm trying to execute this Jasmine test via grunt. When I execute the this via Grunt, I get an error. The error confuses me because the grunt-jasmine-node module is defined in my package.json file. I've also checked that it got downloaded when I ran npm install. Either way, here is the error:
>> Local Npm module "grunt-jasmine-node" not found. Is it installed?
Running "jasmine:testShared" (jasmine) task
Testing jasmine specs via PhantomJS
>> Error: notloaded: Module name "../" has not been loaded yet for context: _. Use require([])
>> http://requirejs.org/docs/errors.html#notloaded at
>> ..\..\C:\Tests\jasmine\_SpecRunner.html:21
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:12 v
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:26 h
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:31
>> ..\..\C:\Tests\jasmine\node_modules\glob\examples\g.js:1
>> Error: notloaded: Module name "../" has not been loaded yet for context: _. Use require([])
>> http://requirejs.org/docs/errors.html#notloaded at
>> ..\..\C:\Tests\jasmine\_SpecRunner.html:21
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:12 v
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:26 h
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:31
>> ..\..\C:\Tests\jasmine\node_modules\glob\examples\usr-local.js:1
>> ReferenceError: Can't find variable: module at
>> ..\..\C:\Tests\jasmine\node_modules\glob\glob.js:37
>> Error caught from PhantomJS. More info can be found by opening the Spec Runner in a browser.
Warning: SyntaxError: Parse error Use --force to continue.
Aborted due to warnings.
This is so frustrating. My code can be downloaded from here. I've been working on this for 2 days now. If I don't get it done today, I'll have to go back to .NET. Can someone please help me get this resolved? I really want to keep moving in this direction. I believe this is just something really small.
grunt-jasmine-node is not defined in your package.json as Andy pointed out.
You can define and install it using the command npm-install --save grunt-jasmine-node that will fix that error.
This issue might be related https://github.com/gruntjs/grunt/issues/232.
Also you might want to seperate your dev dependencies and normal dependencies.
npm install --save-dev module includes the module in 'devDependencies' config, and
npm install --save module includes the module in dependencies config, in package.json.
I hope this will fix your problem, i am looking for that 500 bounty.
Edit
Edit:
Also it appears to me that you are mixing your client libraries with the server sides.
Namely you include vendor path like this:
File: tasks/options/jasmine.js
options: {
specs: "shared/tests/unit/**.tests.js",
// server libs
vendor: "node_modules/**/*.js",
// should be browser libs
// vendor: "shared/libs/lodash/dist/lodash.js",
}
All your node_modules folder gets included inside the browser.
Really what you should be doing is define your libraries in shared/libs
and use that path for the vendor option.
You can use bower to automatically install them.
And finally your actual code,
var _ = require('lodash');
_.mixin({
'myFunction' : function(s) {
return 'Hello ' + s;
}
});
module.exports = _;
This is again server side code, that gets loaded into the browser.
You should write this for the browser.

Categories

Resources