I would like to configure one script findFruit.js that is written under nodeJs, wrapping into a library and make it useful from the other project that may be written by nodeJs or es6 code. How should I configure rollup from a es6 module?
I get the error once using
import * as obj from './application'
^^^^^^
SyntaxError: Cannot use import statement outside a module
//~/application/src/findFruit.js
function findFruit() {
return 'banana'
}
module.export = findFruit
//~/application/package.json
{
"name": "get a fruit",
"version": "0.0.0",
"description": "test",
"author": "author",
"license": "UNLICENSED",
"main": "dist/findFruit.js",
"scripts": {
"publish": "rm -rf ./dist && rollup -c rollup.config.js",
},
"devDependencies": {
"#rollup/plugin-commonjs": "^15.0.0",
"rollup": "^2.26.11",
"rollup-plugin-auto-external": "^2.0.0"
}
}
//~/application/rollup.config.js
import commonjs from "#rollup/plugin-commonjs";
import pkg from "./package.json";
import autoExternal from "rollup-plugin-auto-external";
export default {
input: 'src/findFruit.js',
plugins: [autoExternal(), commonjs()],
output: {
file: pkg.main,
format: 'cjs',
exports: 'named',
},
};
//under ~/a.js
import * as obj from './application'
obj(});
//import * as obj from './application'
//^^^^^^
//
//SyntaxError: Cannot use import statement outside a module
//under ~/a.js
const findFruit = require('./application').default;
console.log(findFruit())
//no problem
Related
I am writing my first NPM package as a plugin for Vite. I had all the code in my plugin before in a separate file inside the same code base, but now I have split and separated it into a it's own nuget package.
When I use the package in my sample projects and I run npm run dev I get this error which I didn't get before:
failed to load config from C:\Users\cjime\Desktop\Open Source Projects\Vite.NET\dotnet-vite\ClientApp\vite.config.ts
error when starting dev server:
file:///C:/Users/cjime/Desktop/Open%20Source%20Projects/Vite.NET/dotnet-vite/ClientApp/vite.config.ts.timestamp-1674663682047.mjs:4
import ViteDotNet from "file:///C:/Users/cjime/Desktop/Open%20Source%20Projects/Vite.NET/dotnet-vite/ClientApp/node_modules/vite-dotnet/lib/index.js";
^^^^^^^^^^
SyntaxError: The requested module 'file:///C:/Users/cjime/Desktop/Open%20Source%20Projects/Vite.NET/dotnet-vite/ClientApp/node_modules/vite-dotnet/lib/index.js' does not provide an export named 'default'
Which is strange because there is a default export. The following is the only code file used/exposed in the plugin, it's not a large codebase
import type { UserConfig } from 'vite';
import { basename, posix } from 'path';
export type PluginConfig = {
port: number;
appFolder: string;
entrypoint: string;
prodServerOrigin?: string; //Not for initial release. Use when hosting app files in a remote server such as S3 or Azure Blob.
}
function outputOptions (assetsDir: string) {
// Internal: Avoid nesting entrypoints unnecessarily.
const outputFileName = (ext: string) => ({ name }: { name: string }) => {
const shortName = basename(name).split('.')[0]
return posix.join(assetsDir, `${shortName}.[hash].${ext}`)
}
return {
entryFileNames: outputFileName('js'),
chunkFileNames: outputFileName('js'),
assetFileNames: outputFileName('[ext]'),
}
}
export default function ViteDotNetPlugin(entrypoint: string, port: number = 5173, appFolder: string = "ClientApp") {
return ViteDotNet({ port, appFolder: appFolder, entrypoint: entrypoint });
}
function ViteDotNet(config: PluginConfig) {
return {
name: 'ViteDotNet',
enforce: "post" as const,
config: (userConfig: UserConfig/*, { command, mode }*/) => {
//https://vitejs.dev/config/server-options.html#server-origin
return {
server: {
origin: `http://localhost:${config.port}`,
hmr: {
protocol: 'ws'
}
},
build: {
outDir: `../wwwroot`,
emptyOutDir: false,
manifest: `${config.appFolder}/manifest.json`,
rollupOptions: {
// overwrite default .html entry
input: config.entrypoint,
output: outputOptions(config.appFolder)
}
}
}
}
};
};
Now, I realize this might be because of an error on my part when configuring the package.json file. Here it is:
{
"name": "vite-dotnet",
"version": "0.2.8",
"description": "Integration plugin for ASP.NET Core and ViteJS",
"main": "lib/index.js",
"keywords": [
"vite",
"vite-integration",
"react",
"svelte",
"vue",
"solidjs",
"lit"
],
"repository": {
"type": "git",
"url": "git+https://github.com/techgems/Vite.NET"
},
"type": "module",
"files": ["lib/**/*"],
"types": "lib/index.d.ts",
"author": "TechGems",
"license": "MIT",
"scripts": {
"build": "tsc"
},
"devDependencies": {
"#types/node": "^18.11.18",
"tslib": "^2.4.0",
"typescript": "^4.6.4",
"vite": "^3.2.3"
}
}
Here is also a link to the entire codebase of the plugin:
https://github.com/techgems/Vite.NET/tree/master/ViteDotNet/Plugin
as well as the NPM package: https://www.npmjs.com/package/vite-dotnet
Thanks in advance and please let me know if you need more information.
in vite.config.js
import { defineConfig } from 'vite'
import path from 'path'
export default defineConfig({
build: {
target: 'es2015',
manifest: true,
minify: true,
reportCompressedSize: true,
lib: {
entry: path.resolve(__dirname, "main.js"),
fileName: "main",
formats: ["es", "cjs"],
},
rollupOptions: {
external: [],
output: {
dir: 'dist'
}
},
},
})
in file main.js
import functions from './functions'
export { functions }
in file functions.js
const isPrime = (n) => {
for (let i = 2; i < n; i++) {
if (n % i === 0) {
return false;
}
}
return true;
}
export default isPrime
in file package.json
{
"name": "vite-project",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"path": "^0.12.7",
"vite": "^4.1.0"
}
}
The idea is that this package can be used:
in the browser
main.isPrime(50)
or
import Main from 'main';
the error appears only in the production file /dist/main.js when I use it in the browser:
Uncaught SyntaxError: Unexpected token 'export'
Thank you for reading
I have changed this line in main.js file
// export { functions }
to
window.functions = functions
but when i wanted to do this it didn't work
import Main from 'main';
So I have a Svelte application with TypeScript enabled but now I am having an issue for running it :
[!] Error: Unexpected token (Note that you need plugins to import files that are not JavaScript)
src\api.ts (4:7)
2:
3: export default class API {
4: url:string;
^
5:
I don't understand because the app was working before, and suddenly raised this error.
It seems that some versions related to TypeScript for Svelte was changed:
{
"name": "...",
"version": "...",
"private": ...,
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv public --no-clear",
"validate": "svelte-check",
"check": "svelte-check --tsconfig ./tsconfig.json" /* + ADDED */
},
"devDependencies": {
"#rollup/plugin-commonjs": "...",
"#rollup/plugin-json": "...",
"#rollup/plugin-node-resolve": "^13.1.3",
"#rollup/plugin-typescript": "^8.0.0",
/* #smui/... stuffs */
"#tsconfig/svelte": "^2.0.0", /* ^1.0.0 -> ^2.0.0 */
"rollup": "^2.67.0",
"rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.5",
"rollup-plugin-svelte": "^7.1.0",
"rollup-plugin-terser": "^7.0.2",
"svelte": "^3.46.3",
"svelte-check": "^2.0.0", /* ^1.0.0 -> ^2.0.0 */
"svelte-preprocess": "^4.0.0",
"tslib": "^2.0.0",
"typescript": "^4.0.0"
},
"dependencies": {
"sirv-cli": "^2.0.2",
"svelte-material-ui": "..."
}
}
/* Note: I replaced some unrelated properties/version by '...'. */
Of course executing npm install didn't help. And if I just remove the :string, it will throw the same error for all other :<type> in the code.
Note that the file is named .ts and that VSCode doesn't detect any syntax error in those files.
Config files (edit)
/* tsconfig.json */
{
"extends": "#tsconfig/svelte/tsconfig.json",
"include": ["src/**/*"],
"exclude": ["node_modules/*", "__sapper__/*", "public/*"]
}
/* rollup.config.js */
import svelte from 'rollup-plugin-svelte';
import commonjs from '#rollup/plugin-commonjs';
import json from '#rollup/plugin-json';
import resolve from '#rollup/plugin-node-resolve';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess';
import typescript from '#rollup/plugin-typescript';
import css from 'rollup-plugin-css-only';
const production = !process.env.ROLLUP_WATCH;
function serve() {
let server;
function toExit() {
if (server) server.kill(0);
}
return {
writeBundle() {
if (server) return;
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
process.on('SIGTERM', toExit);
process.on('exit', toExit);
}
};
}
export default {
input: 'src/main.ts',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js'
},
plugins: [
svelte({
preprocess: sveltePreprocess({ sourceMap: !production }),
compilerOptions: {
dev: !production
}
}),
css({ output: 'bundle.css' }),
resolve({
browser: true,
dedupe: ['svelte']
}),
commonjs(),
typescript({
sourceMap: !production,
inlineSources: !production
}),
json(),
!production && serve(),
!production && livereload('public'),
production && terser()
],
watch: {
clearScreen: false
}
};
No file svelte.config.js
So, I tried executing my app in a docker container, to see if it would work, and got a different error message, much more helpful:
[!] Error: Could not resolve './api.js' from src/App.js`
Indeed, the file is not named ./api.js but ./API.ts (forgot to change the import after renaming it to TS...)
So I changed the import like that:
/* Before (not working) */
import API from './api.js'
/* After (Good) */
import API from './API'
// NB. The filename is really in uppercase for me
TL;DR
Check your import for any import x from file.js which should be a TS file and replace them by import x from file (you should not write the .ts extension)
Explanation:
It is trying to import a JavaScript (.js) file, but find the TypeScript file (.ts) and import it instead (seems like it only cares about the "basename"), but without the TypeScript Support, creating this weird situation where it doesn't reconize TypeScript Syntax inside a .ts file.
I'm trying to set up the project using Node v14.3 and sequelize.
I don't want to use babel-register. Instead of this I set "type": "module" in my package.json and use all ES6 - ES11 features out of the box.
I also want to use sequelize-cli for setting up and applying migrations. Everything works except the following command:
& sequelize db:migrate
Sequelize CLI [Node: 14.3.0, CLI: 5.5.1, ORM: 5.21.11]
Loaded configuration file "config/config.json".
Using environment "development".
== 20200530214311-create-user: migrating =======
ERROR: Must use import to load ES Module: /home/kasheftin/work/tests/chai-http-publication/migrations/20200530214311-create-user.js
require() of ES modules is not supported.
require() of /home/kasheftin/work/tests/chai-http-publication/migrations/20200530214311-create-user.js from /home/kasheftin/.nvm/versions/node/v14.3.0/lib/node_modules/sequelize-cli/node_modules/umzug/lib/migration.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename 20200530214311-create-user.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/kasheftin/work/tests/chai-http-publication/package.json.
We see that under the hood sequelize-cli uses require(). That's not allowed for ES Module. It suggests 3 ways to solve this:
rename 20200530214311-create-user.js to end in .cjs - Can not be done, sequelize-cli does not find migrations that end with .cjs.
Change the requiring code to use import() - I don't want to touch sequelize-cli code.
Remove "type": "module" - I can not because everything stops working.
Is there any other way to make sequelize-cli work? I'm using tests heavily and I want the test database to be prepared automatically before running tests.
A solution is to add a package.json in your migrations folder to override the type: "module" from your main package.json
This package.json would look like this:
{
"type": "commonjs"
}
and your migration file have to look like this:
module.exports = {
up: async (queryInterface, Sequelize) => {
},
down: async (queryInterface, Sequelize) => {
}
};
It works well with nodeJS 14.16.1 & Sequelize 6.6.2 & sequelize-cli 6.2.0
I've had the same issue for months now. Babel register would just not work while using ES module imports and Sequelize cli.
Here's how I eventually got everything to work properly.
I had to copy src to a dist directory. Then override the type in package json. Hopefully this helps out 🍻
.sequelizerc
require('#babel/register')({
presets: [
['#babel/preset-env', { targets: { node: 'current' } }]
]
});
const path = require('path');
const DB_PATH = 'dist/db'; // use dist instead of src directory
module.exports = {
'config': path.resolve(DB_PATH, 'config.json'),
'models-path': path.resolve(DB_PATH, 'models'),
'seeders-path': path.resolve(DB_PATH, 'seeders'),
'migrations-path': path.resolve(DB_PATH, 'migrations')
};
package.json
{
"type": "module",
"engines": {
"node": ">=14.18",
"yarn": ">=1.22"
},
"scripts": {
"start": "node --experimental-specifier-resolution=node src",
"db": "sequelize db:migrate && sequelize db:seed:all",
"predb": "yarn dist",
"dist": "cp -r src dist",
"predist": "rm -rf dist",
"postdist": "node setup-dist.js"
},
"dependencies": {
"#babel/core": "^7.16.0",
"#babel/preset-env": "^7.16.0",
"#babel/register": "^7.16.0",
"sequelize": "^6.8.0",
"sequelize-cli": "^6.2.0"
}
}
setup-dist.js
import { writeFileSync } from 'fs';
const file = './dist/package.json';
const data = '{ "type": "" }'; // to override ESM in main package.json
writeFileSync(file, data);
Reference: https://gist.github.com/elawad/c0af86ea37629ad0538c2b974b4ea0c1
I got this to work by creating a .sequelizerc file to let sequelize know that I am overriding the default paths:
// .sequelizerc
const path = require('path');
const db_path = './';
module.exports = {
'config': path.resolve(db_path, 'config/config.cjs'),
'models-path': path.resolve(db_path, 'models'),
'seeders-path': path.resolve(db_path, 'seeders'),
'migrations-path': path.resolve(db_path, 'migrations')
};
Notice that I am using a config.cjs file. Then just create a migration but change the extension to .cjs as well:
// 20211206164144-create_subjects_table.cjs
const tableName = 'subjects';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable(tableName, {
id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true,
},
title: {
type: Sequelize.STRING,
required: true,
},
created_at: {
type: Sequelize.DATE,
},
updated_at: {
type: Sequelize.DATE,
},
deleted_at: {
type: Sequelize.DATE,
},
});
},
down: async (queryInterface) => {
await queryInterface.dropTable('subjects');
},
};
This is working with Node.js version v16.13.1 and the following package.json:
{
"type": "module",
"dependencies": {
"pg": "^8.7.1",
"pg-hstore": "^2.3.4",
"sequelize": "^6.12.0-beta.1"
},
"devDependencies": {
"sequelize-cli": "^6.3.0"
}
}
I am getting error SyntaxError: Unexpected token import in index file where I am trying to load components via lazy load approach.
const templates = () => import('#/pages/templates');
It works fine if used the syntax:
import templates from '#/pages/templates';
Dynamic import statements are a Webpack feature*, so when you compile code with Jest, dynamic import will be undefined. You can solve this by using babel-plugin-dynamic-import-node in your babel config for tests:
// .babelrc
{
"env": {
"test": {
"presets": [
["es2015", { "modules": false }],
"react",
"stage-0"
],
"plugins": [
"transform-es2015-modules-commonjs",
"dynamic-import-node"
]
}
}
}
*Although it conforms to a TC39 spec