Webpack error from UglifyJS when creating production assets - javascript

I am using Webpack Encore (similar to Webpack) to create asset files.
Everything works well when creating the development files, however when running to command to generate the minified files for production I get an error.
ERROR Failed to compile with 1 errors
app.js from UglifyJS .
Invalid assignment [app.js:131,42]
Unexpected character '`' [app.js:10953,9]
It seems like the issue is caused by two plugins:
jquery-asScrollable and jquery-asScrollbar
In fact commenting out the following lines, the process completes successfully
require('jquery-asScrollable');
require('jquery-asScrollbar');
My package.json file
{
"devDependencies": {
"#symfony/webpack-encore": "^0.17.1",
"animsition": "^4.0.2",
"bootstrap": "4.0.0-beta.2",
"jquery": "^3.2.1",
"jquery-asScrollable": "^0.4.10",
"jquery-asScrollbar": "^0.5.7",
"jquery-mousewheel": "^3.1.13",
"node-sass": "^4.7.2",
"popper.js": "^1.12.9",
"sass-loader": "^6.0.6",
"webpack-notifier": "^1.5.0"
}
}
UPDATE:
app.js
require('jquery-asScrollable');
require('jquery-asScrollbar');
require('jquery-mousewheel');
Any ideas of what the problem might be?

The two plugins make use of ES6 syntax - in this case template literals. Uglify is incompatible with large parts of ES6. You need to either copy those plugins to your project code (so they get transpiled by your Babel) or un-exclude their respective node_modules folders in your Babel transpilation process.
See the template literals (and more ES6) being used here (line 90-93):
Another option is to import/require the minified versions of the plugins from their dist folders.
Example:
require('node_modules/jquery-asScrollable/dist/jquery-asScrollable.min.js')

Related

Why is my Jest code coverage report invalid?

When I generate a Jest code coverage report for my Vue 2.7.X app, the lines shown as covered/uncovered in the report don't make any sense:
The red sections in this report should indicate code that's not covered (executed) by the test suite, but obviously it makes no sense to show comments (lines 290, 291) as uncovered, or to show (part of) line 298 as uncovered when the lines before and after are covered.
I guess what's happening is that the lines which Jest detects as uncovered are not being correctly mapped back to the source code, so there may be a problem with the Babel transpilation.
I generate the code coverage report with yarn jest --coverage and the application source code is written in JavaScript (rather than TypeScript).
some of the dependencies from package.json which may be relevant to the problem are shown below:
"devDependencies": {
"#babel/core": "^7.20.5",
"#babel/preset-env": "^7.20.2",
"#vue/test-utils": "1.3.3",
"#vue/vue2-jest": "29.2.2",
"#vitejs/plugin-vue2": "^2.2.0",
"babel-jest": "^29.3.1",
"http-proxy": "^1.18.1",
"jest": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
"sass": "1.32.13",
"sass-lint": "^1.13.1",
"start-server-and-test": "^1.14.0",
"unplugin-vue-components": "^0.22.12",
"vite": "^4.0.1",
"vite-plugin-rewrite-all": "^1.0.1",
"vue-template-compiler": "^2.7.14"
}
Minimum Reproducible Example
I've created a minimal Git repo that demonstrates the problem.
Clone the repo
Run yarn install && yarn test:unit:coverage to generate the coverage report (or use npm instead)
Open the file coverage/lcov-report/index.html to see the report
If you open the page for components/toaster-message.vue, it says 1/2 branches and 2/3 functions are covered, but none of the lines are marked in red (hideAppMessage should be red because it's not tested).
If you open the page for views/login.vue the lines that are marked in red (uncovered) don't make any sense. There are no tests for this component.
What worked for me was adding coverageProvider: 'v8' to the jest.config.js. I'm not entirely sure why changing coverageProvider works, but seems like vue-jest is having general problems with collecting coverage correctly due to babel dependency changes.
Try adding this to your Jest configuration:
coverageProvider: 'v8'
Then npm run test:unit:coverage.
This worked on Node v16.16.0 and v18.12.1.
jest uses its own version of Babel to transpile your code, but the source map that generates it could be unnacurate or have a differrent version than the one you are using.
You can make sure that jest is using the same version of Babel that you're using in your app by adding the following configuration to your package.json file:
"jest": {
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/babel-jest"
}
}
Also, could it be that even though your package.json has that version you have something else in the package-lock.json?
Looks like solution with coverageProvider: 'v8' added by #morganney works.
For the problem of generating a coverage report.
Failed to write coverage reports:
ERROR: Error: ENOENT: no such file or directory, open 'path\to\file\<<jsx-config-pragma.js>>.html'
Just remove the .ts("\\.(tsx|ts|jsx|js)$") files from configuration (package.json)
...
"transform": {
"\\.(tsx|jsx|js)$": [
"#swc-node/jest",
{
"dynamicImport": true
}
]
},
...

Grunt not including javascript file

This is an angular app. I have a bower.json with a lot of libraries put like this:
"dependencies": {
"angular": "^1.4.0",
"bootstrap": "^3.2.0",
...
"angular-socket-io": "^0.7.0",
"socket.io-client": "^1.7.2"
I run
bower install
and I can see that in the "bower_components"-folder there are folders and files for both "angular-socket-io" and "socket.io-client".
When I then run this command:
grunt serve
I can see that this one is included:
<script src="bower_components/angular-socket-io/socket.js"></script>
However, I cannot find any trace of "socket.io-client". Why? Am I supposed to include this manually? I wonder why then. All the other bower cmopoenents are beeing added autmatically of "grunt serve".
PS: This causes the error "io is not defined" when I try to instantiate a socket frmo a factory.
I guess it was an issue with versions.
Im running angular 1.4.
Having this line:
"socket.io-client": "^0.7.10",
seems made the trick. Before I used latest version of socket.io-client (1.7). And I got incompatibility error.
But now the socket-client is being loaded.

Vue.js browserify Cannot find module

With almost every npm package that I'm trying to use with vue.js 1.0 I receive this error:
{ Error: Cannot find module '!!./../../../node_modules/css-loader/index.js!./../../../node_modules/vue-loader/lib/style-rewriter.js!./../../../node_modules/vue-loader/lib/selector.js?type=style&index=0!./dashboard.vue' from '/Users/jamie/Code/forum/node_modules/vue-html5-editor/dist'
at /Users/jamie/Code/forum/node_modules/resolve/lib/async.js:46:17
at process (/Users/jamie/Code/forum/node_modules/resolve/lib/async.js:173:43)
at ondir (/Users/jamie/Code/forum/node_modules/resolve/lib/async.js:188:17)
at load (/Users/jamie/Code/forum/node_modules/resolve/lib/async.js:69:43)
at onex (/Users/jamie/Code/forum/node_modules/resolve/lib/async.js:92:31)
at /Users/jamie/Code/forum/node_modules/resolve/lib/async.js:22:47
at FSReqWrap.oncomplete (fs.js:117:15)
It drives me nuts! I'm using vue.js with browserify. Looked everywhere on the web:
https://github.com/webpack/css-loader/issues/240
https://github.com/webpack/css-loader/issues/180
https://github.com/webpack/css-loader/issues/295
https://github.com/webpack/css-loader/issues/163
Nothing seems to work! What am I doing wrong!?
2 packages where I've this problem:
https://github.com/lian-yue/vue-upload-component/
https://github.com/PeakTai/vue-html5-editor
My gulpfile:
const elixir = require('laravel-elixir');
require('laravel-elixir-vueify');
require('laravel-elixir-stylus');
elixir(mix => {
mix.browserify('main.js');
mix.styles([
'./node_modules/normalize-css/normalize.css',
'./node_modules/nprogress/nprogress.css',
'./node_modules/sweetalert/dist/sweetalert.css',
]);
mix.stylus('app.styl');
});
A solution would really help me out.
--EDIT--
{
"private": true,
"scripts": {
"prod": "gulp --production",
"dev": "gulp watch"
},
"devDependencies": {
"gulp": "^3.9.1",
"laravel-elixir": "^6.0.0-9",
"laravel-elixir-browserify-official": "^0.1.3",
"laravel-elixir-stylus": "^2.0.3",
"vue-html5-editor": "^0.5.1"
},
"dependencies": {
"browserify": "^13.1.0",
"laravel-elixir-vueify": "^2.0.0",
"normalize-css": "^2.3.1",
"nprogress": "^0.2.0",
"stylus": "^0.54.5",
"sweetalert": "^1.1.3",
"vue": "^1.0.26",
"vue-resource": "^0.9.3",
"vue-router": "^0.7.13",
"vue-spinner": "^1.0.2",
"vue-upload-component": "^2.0.0-beta"
}
}
Those are webpack packages and you are using browserify. If you need to use webpack packages you should be using webpack as your bundler.
I did have a go at installing the vue-upload-component package to see how easy it would be with browserify and elixir but it's awkward to say the least. I didn't get it working because it uses babel transforms to compile the vue files, so first you need to pull them in manually and then you would likely need to write an elixir extension to use those transforms to get it to work. Obviously each webpack package will be different so you would need to do that each time you install one, which is hardly convenient.
I had some luck changing the configuration output of the Vue component I wanted to use to use webpack -p instead of just webpack.
I could then take that output without the hot module code and put it through browserify:
browserify file.js --standalone SomeLibrary > file.browser.js
Where file.js is the webpack -p output, SomeLibrary is the name you want on the global window scope from the browserify packaging, and file.browser.js is your resultant file to include in your project.

Using material-ui in client-side requireJS environment?

I've been researching for a couple hours now on how to include material-ui as a client-side AMD module for my application, and here is the closest I've come. Using grunt-amd-wrap, I used the following grunt task in my Gruntfile:
amdwrap: {
materialui: {
expand: true,
cwd: 'node_modules/material-ui/lib/',
src: ['**/*.js'],
dest: 'client/js/components/',
},
},
and scheduled it to run after material-ui finished transpiling to its lib folder. However, this still poses an issue since the files require() the following modules:
"inline-style-prefixer": "^0.5.1",
"lodash.throttle": "~3.0.4",
"lodash.debounce": "~3.1.1",
"react-addons-transition-group": "^0.14.0",
"react-addons-update": "^0.14.0",
"react-addons-create-fragment": "^0.14.0",
"react-addons-pure-render-mixin": "^0.14.0",
"warning": "^2.1.0"
And I can't figure out how to bundle those to a client-side AMD module in addition to material-ui itself.
In summary: Is there a way to use grunt to convert material-ui's CommonJS syntax to a self-contained AMD module (or set of self-contained AMD modules)? I'd like to avoid using gulp, and I'd prefer to only use browserify if it is absolutely necessary.
I ended up using grunt-webpack. Although it's not an AMD module, I was able to bundle the files I needed along with their dependencies in one output file.

Gulp - Using existing minified files and source maps in combination with non-minified files and source maps

We are using a gulp process that, like most people, compress, uglify, and concat JavaScript files to a single "app.js" file. Some of the files that we are using are distributed via bower and already come pre-minified with source maps. Ideally, instead of re-minifying these files, we just use the .min and .min.map directly. How do we accommodate this?
So, essentially, our JavaScript .src files look like this
'[FILE(S) TO BE UGLIFIED]',
'[FILE(S) ALREADY UGLIFIED]', // these also have map files
'[FILE(S) TO BE UGLIFIED]'
and we want them to all be in one app.min.js and app.min.js.map.
Being these are all copied to a dist directory, its acceptable if we do something like uglify the first set of files, pipe to dist. Take the existing files already uglified + the output from the first batch and concat them (and re-run through sourcemaps) & pipe to dist again, then do the same for the last set.
The gulp plugins that we are already using to do all this are:
"gulp-concat": "2.4.1",
"gulp-uglify": "1.0.1",
"gulp-token-replace": "1.0.1",
"gulp-autoprefixer": "1.0.1",
"gulp-if": "1.2.5",
"gulp-sourcemaps": "1.2.2"
gulp sourcemaps plugin allows you to do exactly that very easily. Pipe its sourcemaps.init function just after gulp.src with options {loadMaps: true} and it will check for existing sourcemaps with the same filename, but .map extension at the end.

Categories

Resources