I have created an application (using vue and webpack) that needs two urls to access REST services. These urls are different per deployment. So I would realy like to have an external configuration file (maybe JSON) that stores those urls.
I did some research and I came upon webpack externals. Added externals to my configuration file:
module.exports = {
...
externals: {
tryout: path.resolve(__dirname, "./test.js")
}
}
test.js is really simple --> export default {url1 : 'https://bla', url2: 'https://bla2'}
From the vue file where I need this file I call:
import Tryout from 'tryout'
console.log(Tryout)
This causes my application to show a blank screen. No errors in the console nor in the npm console screen.
Not sure what is happening. couple of questions:
I am using dev server not sure where to place the test.js file I placed it here : __dirname, "./test.js" so this is in my build directory...
Should I load it in my index.html file like an external libary load?
does anybody has a step by step example? Couldn`t find it online..
This should be simple but no clue since I am not getting any error or message...
Any help would be really helpful!
Related
I'm working with an application that uses Tesseract (OCR) to read text from images.
I would like to take some JS files from node_modules/tesseract.js/dist and make them downloadable in the browser.
I know I can just copy the files to ./public and next.js will serve it statically from there, but then if I update my version of Tesseract, I may need to update those files as well. So maintenance becomes a problem.
My 1st thought is to customize my webpack config to copy the files from node_modules/tesseract.js/dist to ./public/tesseract (or something like that). That would make sure the files get re-copied if I update Tesseract. But I'm not particularly savvy with webpack and haven't figured out how to do that yet.
My 2nd thought was to "proxy" the retrieval of the JS file's content and just make the content available as a "page" in next.js (but this seems super hacktastic).
I feel like this is something that shouldn't be so complicated ... but I've not been able to figure it out myself yet.
Thanks in advance!
Yup agreed, updating your server to serve a node_modules path sounds a bit dangerous.
I personally would just copy over these files with webpack like you mentioned.
Here are the docs on Next.js on how to set up a custom webpack config.
next.config.js
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
webpack: (config) => {
// append the CopyPlugin to copy the file to your public dir
config.plugins.push(
new CopyPlugin({
patterns: [
{ from: "node_modules/tesseract.js/dist", to: "public/" },
],
}),
)
// Important: return the modified config
return config
}
};
I purposefully didn't include the public/tesseract path, I'm not sure if the CopyPlugin will automatically generate missing directories if they don't exist at build time.
I am currently using a WebPack configuration that allows for the direct injection of ReactJS into a site. This compiles all of the React code into a single index.js, and I am trying to code split it because the file is getting very large. Without the code split, bootstrap is not loaded, because I have it as part of my WordPress theme. When I use React.lazy() though, I get 404 errors for 0.js which my developer tools say is caused by bootstrap. Here is my index.js:
const Register = lazy(() => import('./components/register/register')); // Import function
and for the rendering:
<Suspense fallback={<div><Loader/></div>}><div id="container"><Register /></div></Suspense>
With the module imported normally like import Register from './components/register/register'; it works perfectly fine, but as soon as I use lazy, the console begins throwing errors. WebPack compiles correctly either way. Here is a screenshot of the console error:
Any help would be appreciated because I usually use Create-React-App and don't know much about customizing WebPack. Thanks!
I worked very hard to figure out what the root of the issue was, and it turned out that the browser was looking for the 0.js chunk on the https://example.com/register/0.js when the file was in fact sitting at https://example.com/wp-content/themes/theme/build/0.js. A few google searches and some trial and error later I figured out a WebPack config that would allow for this to compile correctly. It is as follows:
output: {
path: path.resolve(__dirname, 'build'),
publicPath: '/wp-content/themes/theme/build/'
},
Just documenting this in case someone else has the same issue.
We have several applications deployed which were with plain html and js.
These applications should be completely independent modules without affecting other applications deployed.
But we should be able to load from one application to another if the situation needs which will be dynamically decided by business.
We were able to load different application screens by simply giving the relative path as there was no dependency bundling previously.
Now we are converting them to react applications with webpack as bundler.
Here we have to use dynamic import if we are going to need something dynamically. That also works on patterns which should be given at the build time.
So is there any way to achieve this kind of dynamic pattern using webpack bundler?
For importing screen components, code is something like below,
Promise.all(reqList.map(modulePath =>
{
return import(/* webpackMode: "lazy-once" */`../../../${modulePath}.jsx`)
})).then(modules => {doStuff()})
As they all are parallelly deployed applications we are trying to go back 3 folders (i.e, root folder like webapps in tomcat) and access the other application path, which will be derived dynamically in modulePath variable.
So while importing, webpack tries to import from the chunks which has already been loaded on first application launch. But this loaded chunks are not having the screens from other applications yet.
We have tried giving each jsx files as entry points in webpack which did created independent files but if we make them as entry files, they should be attached to the index.html manually, Which would cease export in jsx to work.
My wepack config is something like below,
function getEntries(pattern) {
const entries = {};
glob.sync(pattern).forEach((file) => {
let fileName = file.substr(0,file.indexOf("."));
entries[fileName.replace('src/', '')] = path.join(__dirname, file);
});
return entries;
}
let jsxFiles = getEntries('src/**/*.jsx');
console.log(Object.keys(jsxFiles));
module.exports = {
entry: jsxFiles,
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].js',
chunkFilename: "AppId"+'.js'
}
}
The first application is loading fine as webpack is able to find the bundled chunks but when we try to load different application screen components, dynamic importing fails saying module not found.
Is there any way we can achieve this kind of dynamic imports?
Thanks for going through such a long post, I didn't had a choice but to explain.. :)
Essentially, you are looking for dynamic module loading. You would need to webpack each module separately.
To load them, you have several options
Use the browser's native import(), but IE, Edge, and Firefox don't support it, yet
Use a module loader library
SystemJS
RequireJS, although it's rather old
In case of going with a module loader, you need to webpack your modules to the corresponding System.register or AMD formats
Current situation
We have many clients using our client application software. The problem is we need to connect to different REST endpoints. The base URL is always different.
Currently we're using a config.json file which we're manipulating during release. A simple example
config.json
{
"endpoint": "http://localhost/api"
}
During startup of our application we're doing an HTTP call to get this file. For further API calls we're using the endpoint provided by the config.json file.
Desired outcome
What we really want is this becomes part of our applications instead of doing the HTTP call. We're using webpack to build our application.
In our dataservice layer we want to do something as follows:
import config from './config';
// use config.endpoint;
config.js
export default {
endpoint: "http://localhost/api"
};
We can override the confg.js file during build. But since we have many clients (+- 30) we don't want to build for each client. We just want one build and modify the config.js file during release with the correct configuration.
Basically we want webpack to ignore the file during build and copy the file to the output folder + inject it in index.html.
I've done some research and I'm not sure how to solve ths issue. Maybe the initial HTTP call isn't that bad afterall?
Edit: the endpoint is just an example, we have more client specific configuration defined in our client app
Ok, this was easier than expected. I simply added a new entry with the config file.
entry: {
config: "./src/config.ts",
app: "./src/main.ts"
}
In the UglifyJsPlugin I added an exclude for the config file.
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
exclude: /(config).+/i,
sourceMap: true
}),
The output is a "readable" config file.
I'm working on an application that needs to pull in the ReadiumJS library, which uses AMD modules. The app itself is written in es6 w/ webpack and babel. I've gotten the vendor bundle working correctly, and it's pulling in the built Readium file, but when I try to require any of the modules Webpack says it can't resolve them. Anyone ever do this before with Webpack and RequireJS? Here's some info that may help - not sure what else to include as this is my first time really using Webpack..
Folder Structure
/readium-src
/readium-js
/ *** all readium-specific files and build output (have to pull down repo and build locally)
/node_modules
/src
/app.js -> main entry for my app
/webpack.config.babel.js
webpack.config.js entries
entry: {
vendorJs: [
'jquery',
'angular',
'../readium-src/readium-js/build-output/_single-bundle/readium-js_all.js',
'bootstrap/js/alert.js' //bootstrap js example
],
appJs: './app.js'
}
Trying to require it in app.js
var readiumSharedGlobals = require('readium_shared_js/globals');
I never really got into using RequireJS, so really struggling to understand how to consume that type of module along side other types of modules with webpack. Any help greatly appreciated :)
Update
If I change my app.js to use this instead:
window.rqReadium = require('../readium-src/readium-js/build-output/_single-bundle/readium-js_all.js');
Then it appears to try to load all the modules, but I get a strange error:
Uncaught Error: No IPv6
At this point, I'm unsure of
Should I have to require the entire path like that?
Is this error something from webpack, requirejs, or Readium? Tried debugging, but couldn't find anything useful...
UPDATE 8/12/2016
I think this is related to an issue with a library that Readium is depending on: https://github.com/medialize/URI.js/issues/118
However, I'm still not clear on how to correctly import AMD modules with webpack. Here's what I mean:
Let's say I have an amd module defined in moneyService.amd.js like this:
define('myMoneyService', ['jquery'], function($) {
//contrived simple example...
return function getDollaz() { console.log('$$$'); }
});
Then, in a sibling file, app.js, I want to pull in that file.
//this works
var getDollaz = require('./moneyService.amd.js');
//this works
require(['./moneyService.amd.js'], function(getDollaz) { getDollaz(); }
//this does not
require(['myMoneyService' /*require by its ID vs file name*/], function(getDollaz) {
getDollaz();
}
So, if we cannot require named modules, how would we work with a third party lib's dist file that has all the modules bundled into a single file?
Ok, so there's a repo out there for an Electron ePub reader using Readium, and it's using webpack: https://github.com/clebeaupin/readium-electron This shows a great way to handle pulling in RequireJS modules with webpack.
One super awesome thing I found is that you can specify output.library and output.libraryTarget and webpack will transpose from one module format to another... freaking awesome! So, I can import the requirejs module, set output library and libraryTarget to 'readium-js' and 'commonjs2' respectively, then inside my application code I can do import Readium from 'readium-js';