how to require webpack bundles in js files - angularjs

I want to require two bundle files from webpack in an app.js that also gets bundled. My folder looks like this:
MyApp
|-app
| -app.js <-this gets bundled
|-hero
| -hero.module <- this gets also bundled
| -some other stuff that will be bundled in hero.bundle.js
|-crisis
| -crisis.module <- gets bundled
| -more stuff that gets bundled in crisis.bundle.js
-
So far so good.
I want to require hero.bundle.js and crisis.bundle.js in the app.js, because I am lazy loading / routing with my COmponent Router in app.js.
But I get constantly the Error, that the modules couldn't be found.
Example Syntax of one of the requires:
path: '/heroes/...',
name: 'Heroes',
loader: function () {
// lazy load Heroes
return $ocLazyLoad.load([require('./dist/heroes.bundle.js')])
.then(function () {
return 'heroes';
});
}
Do I do something wrong?
Thanks in advance :)

I got the solution:
Webpack didn't find my files. The path searched
C:/someFolders/heroApp/app/dist/heroes.bundle.js
altough it was
C:/someFolders/heroApp/dist/heroes.bundles.js
setting two dots was the solution:
require('../dist/heroes.bundle.js')

Related

react-i18next with multiple translation-files

I have a little problem in my application.
I use i18next and react-i18next for the translation and have already included it.
The whole translation comes from 1 file for each language and that is a mess with over 4000 rows :(
Now I want update this so that i18next would take the translation files placed in the different component-folders and their children-folders.
The folder-structure should look like this after the update:
scr
- components
-- Header
---translations (en/translation.json, de/translation.json)
-- Dashboard
--- translations (en/translation.json, de/translation.json)
--- Menu
---- translations (en/translation.json, de/translation.json)
---- ExampleComponent.tsx
---- ...
--- Cards
---- translations (en/translation.json, de/translation.json)
...
I already figured out how I can handle the automatic export via babel and babel-i18next-plugin with the "namespace"
So, my code (example Menu) would be written like this:
const { t } = useTranslation("Dashboard/Menu")
const explString = t("ExampleComponent.ExampleString","This is an example")
In babel I placed the plugin like this:
[i18next-plugin, {"outputPath": "src/components/{{ns}}/translations/{{locale}}/translation.json"}]
This runs without problems. It takes the namespace as a folder-structure and places the translation-files into the translation-folder including the correct keys.
Now, how I can tell i18next, where to find the translation-files?
I could only figure out that I can import the files (file-by-file) inside a resource.
I tried backend plugins (html-backend, async-storage-backend, local-storage-backend and filesystem) with
backend: { loadPath: "components/{{ns}}/translations/{{lng}}/translation.json" }
(The i18next.ts is placed inside src/)
and I get the warnings that the keys aren't found.
Also, you can see that I use TypeScript.
In my webpack I tried it with the ts-i18next-loader with this inside the webpack configuration file:
{
test: /\translation.json$/,
exclude: /node_modules/,
loader: 'i18next-ts-loader',
options: {
localeFilesPattern: 'src/components/{{ns}}/translations/{{lng}}/translation.json',
},
},
If I only had 5-6 translation-files for each language / namespace it would not be a problem to put it inside the resource but at the end I have more than 100 files for each language.
Would be nice if anyone had a solution to my problem. If you need any further information I can update the post.
Cheers
There's an alternative plugin to be used, suggested in the official documentation: https://www.i18next.com/how-to/add-or-load-translations#lazy-load-in-memory-translations
i18next-resources-to-backend helps to transform resources to an i18next backend. This means, you can also lazy load translations, for example when using webpack:
import i18next from 'i18next';
import resourcesToBackend from 'i18next-resources-to-backend';
i18next
.use(resourcesToBackend((language, namespace, callback) => {
import(`./locales/${language}/${namespace}.json`)
.then((resources) => {
callback(null, resources)
})
.catch((error) => {
callback(error, null)
})
}))
.init({ /* other options */ })
Found the solution.
After i included the "webpack backend for i18next" it solved the problem and the translation gets the correct file.
i18next webpack backend by SimeonC

Importing self-created libraries in reactjs

I'm using React and ES6 using babel and webpack. I am very new to this ecosystem.
I am trying to import some common utility functions into my jsx file but react is unable to find the file
homepage.jsx
var pathToRoot = './../..';
import path from 'path';
import React from 'react';
import ReactDOM from 'react-dom';
var nextWrappedIndex = require(path.join(pathToRoot,'/lib/utils.js')).nextWrappedIndex;
//some react/JSX code
utils.js
var nextWrappedIndex = function(dataArray) {
//some plain js code
return newIndex;
}
exports.nextWrappedIndex = nextWrappedIndex;
Directory structure is as follows:
src
|--app.js
|--components
| |--homepage
| |--homepage.jsx
|
|--lib
| |--utils.js
I am on a windows 10 machine and was facing issues during compilation providing the path by any other means. Using path.join solved compilation issue but the browser while rendering throws this error
Uncaught Error: Cannot find module '../../lib/utils.js'.
How do I accomplish this?
Also, is this the best way to do it(if altogether it is way it is supposed to be done in such ecosystem)?
One of the best and easiest way I have found in such a setup is to use Webpack aliases.
Webpack aliases will simply associate an absolute path to a name that you can use to import the aliased module from anywhere. No need to count "../" anymore.
How to create an alias?
Let's imagine that your Webpack config is in the parent folder of your src folder.
You would add the following resolve section in your config.
const SRC_FOLDER = path.join(__dirname, 'src')
resolve: {
alias: {
'my-utils': path.join(SRC_FOLDER, 'lib', 'utils')
}
}
Now, anywhere in your app, in any of your modules or React component you can do the following:
import utils from 'my-utils'
class MyComponent extends React.component {
render () {
utils.doSomething()
}
}
Small note about this method. If you run unit tests with a tool like enzyme and you don't run the component tested through Webpack, you will need to use the babel-plugin-webpack-alias.
More info on Webpack website: Webpack aliases
I solved this by replacing
var nextWrappedIndex = require(path.join(pathToRoot,'/lib/utils.js')).nextWrappedIndex;
with
import nextWrappedIndex from './../../lib/utils.js';
I tried to reproduce your code and Webpack printed me the following error:
WARNING in ./app/components/homepage/homepage.jsx
Critical dependencies:
50:0-45 the request of a dependency is an expression
# ./app/components/homepage/homepage.jsx 50:0-45
It means that Webpack couldn't recognize your require() expression because it works only with static paths. So, it discourages the way you are doing.
If you would like to avoid long relative paths in your import, I'd recommend you to set up Webpack.
First, you can set up aliases per Amida's answer.
Also, you can set up an extra module root via resolve.modules to make webpack look into your src folder, when you are importing something absolute, like lib/utils.js

React-router issues using static-render-webpack-plugin

I just started working with React last week, and I'm having trouble following a tutorial for the static-render-webpack-plugin.
I've put the code online at GitHub if you want to take a closer look.
After following the tutorial and making a couple of changes (I added babel-core, I changed the js loader to babel-loader and the entry point url needed a small correction), when I try to run webpack -p to generate the static files I get the following error:
ERROR in ./src/entry.js
Module build failed: SyntaxError: .../src/entry.js: Unexpected token (10:2)
8 |
9 | const routes = (
> 10 | <Route path="/" handler={RootPage}>
| ^
I think it might have something to do with the changes made with the latest version of react-router. I'm using the latest version, but the syntax for the tutorial looks like it might have been written prior to v.1.0. For example, I think the part of the tutorial that says to add this to the src/entry.js file:
if (typeof document != 'undefined') {
Router.run(routes, path, (Root) => {
React.render(<Root/>, document);
});
}
probably needs to be rewritten to something like this (but I'm not sure if this is quite right):
if (typeof document != 'undefined') {
ReactDOM.render(routes, document);
}
There's obviously more going on though since I get the same error message when I try that rewritten snippet then run webpack-dev-server -- which is the only time it should hit that code. (Yes, I added import ReactDOM from 'react-dom'; to the top of the page and "react-dom": "^0.14.7", to the package.json.)
I am sure this part (also on src/entry.js) needs to be rewritten to match the latest react-router too but I'm not sure how:
export default function(path, props, callback) {
Router.run(routes, path, (Root) => {
const html = React.renderToString(<Root/>);
callback('<!doctype html>' + html);
});
}
Thanks in advance for any help or hints you can give.
Your code is breaking because Webpack doesn't know how to transpile the JSX to ES5. You've specified babel-loader as your loader for JS files in your webpack config, but unfortunately Babel 6 does not do anything out of the box, you need to include "plugins" that contain the rules for compiling different syntaxes down to ES5. In this case, you'll want the es2015 preset to support all ES6 syntax, and the react preset to support JSX. You're also missing the extract-text-webpack-plugin you are trying to import into your webpack config. Snag these through NPM:
npm i -D babel-preset-2015 babel-preset-react extract-text-webpack-plugin
Then, add the presets to your webpack.config.js file in the loaders section for js/jsx files:
{
test: /\.(js|jsx)?$/,
loader: 'babel',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}
I forked your repo and made these changes and was able to get a bit further through the compilation process. It seems like there are module dependencies specific to your project you'll still need to resolve.

How do I control the order files are loaded in karma config

I'm testing an Angular app with Karma. I've got everything working, but it seems like I'm doing something wrong.
https://gist.github.com/guyjacks/7bca850844deb612e681
Karma will throw the following error if I comment out 'app/notes/notes.main.js' :
Uncaught Error: [$injector:nomod] Module 'notes.main' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.4.3/$injector/nomod?p0=notes.main
at /Users/guyjacks/projects/adr-demo/node_modules/angular/angular.js:1958
I don't want to have to manually list each application file to control the order in which each file loads. Am I don't something wrong or do I just have to list each file in the order I want?
---- Solution based on the accepted answer ----
My app is organized into modules as recommended by the Angular Style Guide: https://github.com/johnpapa/angular-styleguide.
'app/app.module.js',
'app/**/*.module.js',
'app/**/*.service.js',
'app/**/*.controller.js',
'app/**/*.directive.js',
'app/**/*.js'
I don't think the following lines are necessary above
'app/**/*.service.js',
'app/**/*.controller.js',
'app/**/*.directive.js'
when each module has an angular module declared in the *.module.js file like my app does.
That said, if you did need to explicitly load services before controllers & controllers before directives then this would be the way to do it.
Update : I could not see your karma file, now Gist link is fixed.
The point in notes[.]main.js is causing the problem,
So, 'app/**/*.js' is not matching notes.main.js.
Try now like this : app/**/*. *.js
=============================================================
Before update :
You have to load the modules that you app depends on, in karma config. file :
module.exports = function(config) {
config.set({
.......
// list of files / patterns to load in the browser
files: [
'./client/app/vendors/angular/angular.js',
// =====> load Your modules here ...
'./client/app/app.js',
'./client/app/controllers/*.js',
'./client/app/directives/*.js',
'./client/app/services/*.js',
'./test/client/unit/**/*.js'
],
.....
}) }

One Backbone.js app using require.js depends on another: how do I include the child?

I wrote a backbone.js app that uses require.js and is broken up with models/, collections/ and so forth. I then wrote another app that depends on the first app (and some other things. The files are laid out like so:
/scripts/appA/
models/
collections/
views/
/scripts/appNeedsA/
models/
collections/
views/
What do I put in the needsA to require appA? The below seems logical to me but doesn't work. If I use ../../appA, that finds appA but IT's dependencies can't be found because the root is wrong.
define(
['underscore', 'backbone', '../appA'],
function (_, Backbone, appA) {
...
}
It might not be the answer you were hoping for but, here's one approach:
https://github.com/busticated/RequireLoadingExample
The idea is that you define your module deps using the path the consuming application will use, then in the consumed app you alias the path appropriately.
In my example, I have a top-level main.js file which pulls in both app1.js and app2.js modules. Both of these modules depend on modules within their own sub-directories - e.g. app1.js uses one/mods/a.js and one/mods/b.js. I have another main (main-one.js) file that lives a level down inside the one/ directory. This file calls:
require.config({
paths: {
'jquery': 'libs/jquery',
'one': '.'
}
});
So now when app1.js loads, the one/mods/a.js path is translated to ./mods/a.js and is found / loaded without issue.
You should be able to fork my repo above and load index.html & one.html in a browser with js console open to see it all work.
Hope it helps!
The proper solution is to:
define(
['underscore', 'backbone', 'appA/views/whatever'],
function (_, Backbone, appAWhateverView) {
...
}
and to set your require.config paths to include:
require.config({
paths: {
appA: '../appA'
}
});

Resources