Force Browserify to transform dependencies? - node.js

I'm working on two Node packages at once, let's call them Library and Consumer. Library is responsible for rendering a bunch of stuff in the browser. All Consumer does is import Library from 'library' and call Library(someConfigHere) -- it's basically just a test to make sure Library is doing what I expect in the browser.
I've npm linked Library into Consumer and am trying to run Browserify on Consumer, but I get this error: ParseError: 'import' and 'export' may appear only with 'sourceType: module'. Library does indeed contain an ES6 export statement, so I'm guessing that Browserify is only running against Consumer and not Library.
So my question is: is there any way to force Browserify to transform dependencies as well?
This is my package.json:
{
"name": "consumer",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "budo index.js --port $PORT",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-preset-es2015": "^6.13.2",
"babel-preset-react": "^6.11.1",
"babelify": "^7.3.0",
"browserify-shim": "^3.8.12"
},
"browserify": {
"transform": [
"babelify"
]
},
"babel": {
"presets": [
"es2015",
"react"
]
}
}
This is Consumer's index.js:
import Library from 'library' // <= this is what isn't getting babelified
console.log(Library);
This is Library's index.js:
export default (config) => {
console.log('Testing testing')
}

Browserify transforms can be configured to be global, which means they will be applied to files within node_modules, too.
The configuration is per-transform. With babelify, you'd configure it like this:
browserify().transform("babelify", {
global: true
})
Or, if you are using the command line, like this:
browserify ... -t [ babelify --global ] ...
Or, to configure it in the package.json, it should be something like this (note the added square brackets):
"browserify": {
"transform": [
["babelify", { "global": true }]
]
}
Babelify also implements an ignore option, so it would be possible to configure it to transform only the files within node_modules that you want it to. There is more information here.
Another solution would be to include a similar browserify/babelify configuration in your library module's package.json. When processing dependencies, Browserify will check said dependency's pacakge.json files for transforms and will apply any that are configured.

Related

Import HTML as string and test with Jest

I'm using sveltekit and I can't use the files api to import html templates. So I decided to import by writing a module that imports the content of the document as a string (described here).
// src/global.d.ts
/// <reference types="#sveltejs/kit" />
declare module '*.html' {
const content: string
export default content
}
So far so good, but now I need to test the code and jest can't interpret the code.
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
/home/developer/workspace/src/assets/html/confirm_email.html:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){<!DOCTYPE html>
^
SyntaxError: Unexpected token '<'
I don't understand how jest understands the .d.ts files... How do I get to test the code?
Do you install #babel/plugin-transform-runtime"?
I share my config for jest/svelte-jester..
I have:
jsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"$lib": ["src/lib"],
"$lib/*": ["src/lib/*"]
}
},
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"],
}
svelte.config.js
import vercel from '#sveltejs/adapter-vercel'
/** #type {import('#sveltejs/kit').Config} */
const config = {
kit: {
adapter: vercel(),
vite: {
define: {
'process.env': process.env,
},
},
},
transform: {
"^.+\\.svelte$": ["svelte-jester", { "preprocess": true }]
}
};
export default config;
babel.config.json
{
"presets": [
["#babel/preset-env", { "modules": "auto" }]
],
"plugins": ["babel-plugin-transform-vite-meta-env","#babel/plugin-transform-runtime"]
}
jest.config.js
export default {
"transform": {
"^.+\\.js$": "babel-jest",
"^.+\\.svelte$": "svelte-jester",
},
"moduleFileExtensions": ["svelte", "js"],
"testEnvironment": "jsdom",
"setupFilesAfterEnv": ["#testing-library/jest-dom/extend-expect"]
}
and whole package.json
{
"name": "sveltekit",
"version": "0.0.1",
"scripts": {
"dev": "svelte-kit dev",
"build": "svelte-kit build",
"package": "svelte-kit package",
"preview": "svelte-kit preview",
"test": "jest src",
"test:watch": "npm run test -- --watch"
},
"devDependencies": {
"#babel/core": "^7.16.12",
"#babel/plugin-transform-modules-commonjs": "^7.16.8",
"#babel/plugin-transform-runtime": "^7.17.0",
"#babel/preset-env": "^7.16.11",
"#supabase/supabase-js": "^1.29.1",
"#sveltejs/adapter-auto": "^1.0.0-next.7",
"#sveltejs/kit": "^1.0.0-next.215",
"#sveltejs/svelte-virtual-list": "^3.0.1",
"#testing-library/svelte": "^3.0.3",
"autoprefixer": "^10.4.1",
"babel-jest": "^27.4.6",
"babel-plugin-transform-vite-meta-env": "^1.0.3",
"jest": "^27.4.7",
"postcss-load-config": "^3.1.1",
"prettier": "^2.5.1",
"prettier-plugin-svelte": "^2.5.1",
"svelte": "^3.44.0",
"svelte-jester": "^2.1.5",
"svelte-lazy": "^1.0.12",
"tailwindcss": "^3.0.8",
"ts-jest": "^27.1.3"
},
"type": "module",
"dependencies": {
"#fontsource/fira-mono": "^4.5.0",
"#lukeed/uuid": "^2.0.0",
"#testing-library/jest-dom": "^5.16.1",
"cookie": "^0.4.1",
"svelte-lazy-image": "^0.2.0",
"swiper": "^8.0.3"
},
"testEnvironment": "jsdom"
}
I hope it will help you.I had a lot of troubles too with setting up jest..
1.Import html as string
I solved the problem using another approach...
I'm using a resource of vite to import the html file as an asset, as can be seen here in the documentation
import confirm_email_template from '../../../assets/html/confirm_email.html?raw'
2.Test using Jest
For production it works perfectly, but for unit testing the code breaks because Jest can't import the asset as a module.
So the second part of the problem was fixed (I don't know if this is the best practice) using asset mocks.
// jest.config.cjs
{
⋮
moduleNameMapper: {
⋮
'([a-zA-Z_ ]+\\.html)\\?raw$': '<rootDir>/__mocks/$1.cjs'
}
⋮
}
To make it work, I created the following folder structure:
__mocks
|
confirm_email.html.cjs
another_asset_mocked.html.cjs
The confirm_email.html.cjs looks like this:
// __mocks/confirm_email.html.cjs
module.exports = '<html>content<html>'

Import & Export ES6 keywords in Jest & Mozilla extension development

I'm edveloping a Mozilla Firefox extension using Node.js and I'm trying to cover my implementation with unit tests using Jest.
So my package.json looks like so:
{
"name": "keep-your-session",
"version": "0.1.0",
"description": "Mozilla Firefox extension plugin to store and manage browsing sessions",
"main": "manifest.json",
"scripts": {
"test": "jest"
},
"type": "module",
"jest": {
"testEnvironment": "jest-environment-node",
"transform": {}
},
"repository": {
"type": "git",
"url": "git+https://github.com/BartoszKlonowski/keep-your-session.git"
},
"engines": {
"node": ">=13.0.0"
},
"keywords": [
"Firefox",
"Extension",
"Plugin",
"Session"
],
"author": "Bartosz Klonowski",
"license": "GPL-3.0-or-later",
"bugs": {
"url": "https://github.com/BartoszKlonowski/keep-your-session/issues"
},
"homepage": "https://github.com/BartoszKlonowski/keep-your-session#readme",
"devDependencies": {
"#babel/preset-env": "^7.14.7",
"eslint": "^7.28.0",
"jest": "^27.0.5",
"web-ext": "^6.1.0"
}
}
To test some of logic functions I used export syntax to export functions in it and import them in the test implementation file.
Two problems appeared:
1. Jest does not recognize import, export keywords throwing an error:
FAIL __tests__/content.tests.js
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
...
Details:
P:\Projekty\KeepYourSession\__tests__\content.tests.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { eventTargetIDToCommand } from '../src/popup/MainPopup';
^^^^^^
SyntaxError: Cannot use import statement outside a module
2. Extension stopped working - it works when there's no export in the file, so obviously it fails to launch the extension due to lack of transpiled/packed sources.
I've searched a lot for this problem and tried to add different plugins of Babel, or configure it in various ways, but obviously there's something missing and I just don't know what.
So my question is:
How to correctly configure my environment to transpile all the sources correctly for Mozilla Firefox extension and for Jest testing?

gulp-merge fails to output gulp-main-bower-files after .pipe

I have a css build task that merges resources from bower dependencies and my own css.
The build task is part of project that uses git source control. The project has been running correctly for well over a year.
Up until yesterday, everything was working correctly on my windows laptop, when I reinstalled my npm dependencies that run the build task.
Below is a simplified example
gulpfile.js
var gulp = require('gulp'),
$ = require('gulp-load-plugins')();
gulp.task('default', function () {
return $.merge (
gulp.src('./bower.json')
.pipe($.mainBowerFiles('**/*.css', {
includeDev: 'exclusive',
group: 'css'
})
),
gulp.src(['./source/css/styles.css'])
)
.pipe($.plumber())
.pipe($.concat('stylesheet.css'))
.pipe(gulp.dest('./build/css'))
});
package.json
{
"name": "merge",
"version": "1.0.0",
"description": "",
"main": "gulpfile.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"gulp": "^3.9.1",
"gulp-concat": "^2.6.1",
"gulp-load-plugins": "^1.5.0",
"gulp-main-bower-files": "^1.6.2",
"gulp-merge": "^0.1.1",
"gulp-plumber": "^1.1.0",
}
}
And bower.json
{
"name": "merge",
"description": "",
"main": "gulpfile.js",
"authors": [
""
],
"license": "ISC",
"homepage": "",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"devDependencies": {
"normalize-css": "^7.0.0",
"reset-css": "^2.2.1"
},
"group": {
"css": [
"reset-css",
"normalize-css"
]
}
}
Prior to yesterday the task would merge both sources declared in $.merge(...). Since yesterdays' npm install I am finding that the merge will only output the result for the first declared source.
After some testing I have found that if I reverse the order of the merge sources than both sources are merged to the set output destination.
var gulp = require('gulp'),
$ = require('gulp-load-plugins')();
// the order of the sources has been reversed
gulp.task('default', function () {
return $.merge (
gulp.src(['./source/css/styles.css']),
gulp.src('./bower.json')
.pipe($.mainBowerFiles('**/*.css', {
includeDev: 'exclusive',
group: 'css'
})
)
)
.pipe($.plumber())
.pipe($.concat('stylesheet.css'))
.pipe(gulp.dest('./build/css'))
});
The problem with this solution is that that output content reversed, which may cause issues with style inheritance etc. This change to a successful output makes me think there may be an issue with how and where .pipe($.mainBowerFiles(...) is declared.
I've also tried replacing installed modules for gulp-merge and gulp-main-bower-files respectively with merge2 and main-bower-files.
Using either one or both solved the problem, however this isn't an ideal workaround as it means an update to the gulp task and installed modules.
This sudden failure to output tasks merge css ( or js ) in my project has real issues for any historic commit or branch in the project.
Is there away I can diagnose the failure of the original $.merge(...), or a way that I can retroactively replace gulp-merge with merge2 across all commits my git project and any branches?

Creating a Node NPM module in 9.2.0 to support older versions of Node

Now that Node 9.2.0 has all the new features of the language, how do I go about creating a node module that is backwards compatible with older versions?
If I have a small module that Node 9 supports out of the box, like this.
const {map} = require('lodash')
async function test (...args) {
return map(args, (item) => {
return `${item} yeah`
})
}
module.exports = test
Are there any was to use babel to transpile this for the specific backward version that I would need to support using babel env? Is there any way I can conditionally load those babel development dependencies, say installing this via Node 4 using post-install scripts?
It seems like this is one solution one downside of which is it requires babel-runtime as a dep just in case, even if the current version of node doesn't need it. But in 9.2.0 the code above is the built code, it's simply moved by babel.
Here's an example package.json and on install it will build the src.
{
"name": "example",
"version": "1.0.0",
"main": "lib/index.js",
"scripts": {
"build": "babel src -d lib",
"postinstall": "npm run build"
},
"dependencies": {
"babel-runtime": "^6.26.0",
"lodash": "^4.17.4"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.1"
},
"babel": {
"plugins": [
"transform-runtime"
],
"presets": [
[
"env",
{
"targets": {
"node": "current"
}
}
]
]
}
}

unexpected token import in ES2017 with babel and Jest

I try to use Jest with bablejs and ES2017 in my project, according to the Jest Getting Started page and also Bablejs config for ES2017 this is my .babelrc file :
{
"presets": ["es2017"],
"env": {
"test": {
"presets": ["es2017"]
}
}
}
And my package.json is:
{
"name": "",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest"
},
"repository": {
"type": "git",
"url": ""
},
"author": "",
"license": "ISC",
"bugs": {
"url": ""
},
"homepage": "",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-jest": "^21.2.0",
"babel-polyfill": "^6.26.0",
"babel-preset-es2017": "^6.24.1",
"jest": "^21.2.1"
}
}
When I type npm test to run all my test with jest i get these error :
){import StateList from './StateList';
^^^^^^
SyntaxError: Unexpected token import
It means it doesn't know import.
babel-preset-es2017 does not transform import statements, because it only includes the plugins: syntax-trailing-function-commas and
transform-async-to-generator.
When installing babel-preset-es2017 you also get a warning that it has been deprecated in favour of babel-preset-env, which contains everything that the es201x presets contained and more.
warning babel-preset-es2017#6.24.1: 🙌 Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!
As shown in the Migration guide from es2015 to env, it is a drop-in replacement.
npm install --save-dev babel-preset-env
And change your .babelrc to:
{
"presets": ["env"]
}
Do not confuse babel-preset-env with Babel's env option, which I have removed from your current config, since you are using the exact same presets for the test environment as for any other, so it doesn't have any effect.
You can configure babel-preset-env to only transform features that are not supported by the platform you target, for example { "targets": { "node": "current" } } will only transform features that aren't supported by the Node version you are running. If no targets are specified, it will transform everything. For details see the Env preset documentation.
Note: With the upcoming version 7 of Babel, the official packages will be published under the namespace #babel, which means that babel-preset-env will be #babel/preset-env.

Resources