Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webpack can not pack sqlite3 #698

Closed
wotermelon opened this issue Aug 29, 2016 · 26 comments
Closed

webpack can not pack sqlite3 #698

wotermelon opened this issue Aug 29, 2016 · 26 comments

Comments

@wotermelon
Copy link

cant find module sqlite3

webpack + sqlite3 not working

@tmcw
Copy link
Contributor

tmcw commented Sep 6, 2016

Sorry, this is expected behavior. webpack does not work with native modules, and sqlite3 is one - this is a native binding to the SQLite C library. You might want to try a browser-native solution, like localStorage, or sqlite.js.

@MattJeanes
Copy link

Webpack can and does work with native modules using the webpack-node-loader. I've managed to import sharp using this and it works as expected with no node_modules folder present entirely

@pamtbaau
Copy link

@MattJeanes This sounds promising... Unfortunately, I cannot get it to work with sqlite3 using webpack. Do you perhaps have a working example of electron/webpack/sqlite3?

@MattJeanes
Copy link

@pamtbaau I spent probably about 6 hours trying to get node working under webpack, and I did get it working but there was a lot of hacks in the webpack config to make it do things correctly, and I gave up and just switched back to wiping the folder + doing a yarn install when I upgraded the app

If you're interested, here's my webpack config I made: https://gist.github.com/MattJeanes/1753027da4aca18a3b903fedef5d57e5

Webpack would work perfectly if everything in node was done statically, but in the world of binary modules and dynamic imports, it doesn't work correctly and in my opinion isn't worth the hacks required to make it work.

@pamtbaau
Copy link

@MattJeanes Thanks for your efforts!

6 hours? I've been trying for about a year on and off... :-) I switched over to sql.js a year ago and over to Lovefield on top of IndexedDB about 6 months ago. But sqlite keeps drawing my attention some how...

I will have a look at your solution later today.

@pamtbaau
Copy link

@MattJeanes Yikes, that's an ugly workaround...

Tried several configuration options, but still getting loads of issues thrown at me. Complaints of not being able to resolve node modules like Can't resolve 'fs'.

This morning I implemented a way of bypassing webpack. I open a sqlite database in plain .js file and load this file in the index.html of electron. In my typescript files I import { Database } from "sqlite3"; and declare var db: Database;. Now I can run db.each('select * from...') and have type checking. I don't like it, but it works...

@MattJeanes
Copy link

Generally with Electron apps I've seen the entire node modules packaged up and extracted along with the app code, I'm not sure I've ever seen a webpack'd one, most likely because of these issues. It works OK for small simple apps but when it starts to get bigger and require native modules and ones that use dynamic imports it just messes right up..

@MattJeanes
Copy link

Btw, target: "node", from my config should solve the Can't resolve 'fs' and related problems

@pamtbaau
Copy link

Where did the tightly packed vendor lock-in database and app tools go... They just worked. Now I need to stack package on package on package... waiting for it to fall apart.

Sigh, I'm disclosing my age I think... :-)

@pamtbaau
Copy link

target: 'node' didn't bring me much luck...

Thank you for all the effort and spare time you've put in... I appreciate it.

@MattJeanes
Copy link

@pamtbaau weird - that should have solved that particular error at least.. are you using webpack 1? I'm using webpack 3.. Well good luck on your endeavours, I've officially given up with it personally 😄

@pamtbaau
Copy link

@MattJeanes Finally.... import { Database } from 'sqlite3'; now working in Electron/sqlite3 webpack bundle.

In webpack.config.js add:

module.exports = {
    entry: {
        'app': './root/of/your/app.ts',
    },

    externals: (() => {
        var nodeModules = {};
        fs.readdirSync('node_modules')
            .filter(function (x) {
                return ['.bin'].indexOf(x) === -1;
            })
            .forEach(function (mod) {
                nodeModules[mod] = 'commonjs ' + mod;
            });
        return nodeModules;
    })(),

Fair is fair, I found the solution here: Backend Apps with Webpack (Part I) from James Long

@MattJeanes
Copy link

@pamtbaau all that seems to do is just exclude node_modules from being packed so it doesn't really solve any problems unfortunately..

@eis84
Copy link

eis84 commented Aug 10, 2017

Hi everyone, and thank you for having spoken in public about this issue.
I have the same problem: electron, sqlite3, webpak ... but in addition the project I'm working with uses webpackMerge.
In the webpack.config.js file
There is this code:
Module.exports = [
WebpackMerge (electronMainConf, devConfig),
WebpackMerge (electronRendererConf, devConfig)
]

Why load a main and a render of the page.

As I can add
... ...
Externals: (() => {
Var nodeModules = {};
fs.readdirSync ( 'node_modules')
.filter (function (x) {
Return ['.bin']. IndexOf (x) === -1;
})
.forEach (function (mod) {
NodeModules [mod] = 'commonjs' + mod;
});
Return nodeModules;
}) ()
... ...
??

@ruslanas
Copy link

ruslanas commented Dec 27, 2017

I'm not sure if this is applicable for this project, but here's how I did it in my Electron app.
HTML

<script>
        const sqlite3 = require("sqlite3");
        require("./dist/main.js"); // 
</script>

webpack.config.js

module.exports {
    // ...
    output: {
        filename: "./dist/main.js",
    },
    externals: {
        sqlite3: "sqlite3",
    },
}

@pamtbaau
Copy link

@ruslanas, When using require('sqlite') inside the html page, you are loading it inside Electron's main process. That means the renderer process (your app) has no direct access to sqlite and needs to use ipcRenderer to call main to perform your queries. Main will then return the results using ipcMain.

In that case, your solution works...

I've tried that scenario, but didn't like it:

  • I want all my code (ui logic, business logic and data logic) in one place: my app (= the renderer process)
  • ipc introduces a performance overhead

To be able to import sqlite inside the renderer process commonjs is required:

externals: {
        sqlite3: 'commonjs sqlite3',
    },

Now you can import sqlite inside the renderer process using import { Database } from 'sqlite3';

As a side note:
When using webpack, you don't need to add require("./dist/main.js") to the html page. HtmlWebpackPlugin will do that for you.

@eis84
Copy link

eis84 commented Dec 31, 2017 via email

@pamtbaau
Copy link

@eis84 I have created a repository with an app using Angular5, Bootstrap 4, sqlite3 and webpack. It compiles, runs and can be packaged.

Have a look at it here.

@searene
Copy link

searene commented Feb 12, 2018

I spent several hours on it today and finally solved this issue. The solution is pretty simple, just add externals in webpack.config.js. Here is a sample.

module.exports = {
  entry: 'src/Main.ts',
  ...
  // add the following lines
  externals: {
    sqlite3: 'commonjs sqlite3'
  }
}

The idea is to prevent webpack from parsing sqlite3. If you don't use electron, that's all you need to do. But if you run sqlite3 with electron, you have to make sure the dedicated sqlite3 binary for electron could be generated. Add the following lines in package.json.

"scripts": {
   "postinstall": "install-app-deps"
}

Then install dependencies and build binaries.

npm install --save-dev electron-builder
npm run postinstall

Now try rerunning webpack, it should work now.

@dpatra
Copy link

dpatra commented Mar 14, 2018

Thanks a ton @searene , it works like a charm.

@redplane
Copy link

redplane commented Jun 13, 2018

@searene , I followed your solution above, but now I'm facing with an error:

Cannot find module node_sqlite3.node when I use require('sqlite3')

@wotermelon
Copy link
Author

@redplane Use node-gyp to build the sqlite3 module,because sqlite3 is a native module. try?

@redplane
Copy link

@wotermelon , I tried and worked.
Forgot replying you :).

But when I pack my electron app with sqlite 3 (using require('sqlite3'), my app faces with the same error.

@cliffordfajardo
Copy link

cliffordfajardo commented May 26, 2019

I had the same issue. In addition to doing what @searene said, which was having webpack ignore sqlite3:

module.exports = {
  externals: {
    sqlite3: 'commonjs sqlite3'
  }
}

I later installed electron-rebuild as a dev dependency npm i --save-dev electron-rebuild then added it to my package.json's postinstall script.

//package.json

  "scripts": {
	...,
    "postinstall": "electron-rebuild"
  },

What electron-rebuild will do is build all binaries for you after you.

world29 added a commit to world29/bookshelf that referenced this issue Jun 12, 2022
@RoHanh96
Copy link

RoHanh96 commented May 6, 2023

@redplane

Cannot find module node_sqlite3.node when I use require('sqlite3')

I am facing with this error. Did you fix this?

@Vector-Green
Copy link

Vector-Green commented May 8, 2023

@redplane

Cannot find module node_sqlite3.node when I use require('sqlite3')

I am facing with this error. Did you fix this?

same, if you are building sqlite using webpack and (for example like me trying to bundle node_modules in a single js file + .node files) check sqlite3-loader (more instructions #1700 )
though that works but still not the best solution.
For example you may need to build sqlite.node for different platforms and choose one of the .node files in run-time, probably we would need something line node-pre-gyp-loader for this purpose...
or sqlite improvement

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests