I am working on an application which is build with angular 1.4 and ES5. It is using gulp to minify files. I wanted to use Webpack to leverage features like code-splitting and bundling everything in JavaScript files.
Is it even possible to use webpack with ES5 code as I see almost all blogs about WebPack deal with ES6. Any pointers will be greatly appreciated. Many thanks.
This is how my team did it. Essentially you want to create "entry point files" that perform requires for all your files, since this is how webpack works (it follows the dependency tree). Then point webpack at these "entry point files".
The example at the link above uses TypeScript, but you can easily use ES5 like this:
# ./entry-points/feature1.js
importAll = function(r) {
r.keys().forEach(r);
};
importAll(require.context('./app/feature1', true, /module\.js$/));
importAll(require.context('./app/feature1', true, /(^(?!.*(spec|module)\.js).*\.js)$/));
You can grab a polyfill for Object.keys here, and Array.forEach` here.
Then point to this file from your webpack config like this:
entry: {
'feature1': './entry-points/feature1.js'
}
Related
I am new to Electron, and I have been having some trouble trying to do something simple in an Electron + React application. All I want to do is: Load a 3D model (.glb) located in my src/assets directory from a React component. I created the project using this guide. In a typical React project, I can just import the file directly in my JS module and reference the path in my code. However, with the default Webpack config, the file can't be found. There's obviously a gap in my understanding on how React + Webpack work when loading assets. What am I missing? Any help is greatly appreciated.
Thanks!
Turns out, the Webpack documentation spells out the answer clearly. Who knew? I found a lot of similar questions/answers for older versions of Webpack, so I'll post one here for Webpack 5. It requires a trivial two-line addition to the webpack.rules.js file:
{
test: /\.(png|jpg|gif|svg|glb)$/,
type: 'asset/resource'
}
The key is the asset/resource line. It's new to Webpack 5 and allows the bundling of assets without needing any additional loaders. With that, assets can be included as Javascript modules and Webpack will take care of the rest.
So, one can do:
import modelSrc from "../assets/some_awesome_model.glb";
And that's that. Webpack will spit out a URL such as /9feee593dc369764dd8c.glb, meaning Webpack has located and processed the asset.
my index.php is like the following :
<script src="app/bower_components/jquery/dist/jquery.min.js"></script>
<script src="app/bower_components/angular/angular.min.js"></script>
<script src="app/bower_components/angular-ui-router/release/angular-ui-router.min.js"></script>
<script src="app/bower_components/angular-sanitize/angular-sanitize.min.js"></script>
I would like to add webpack to bundle all these files and minify them
I did not find the way to do that.
I have installed npm , node and webpack
I manged to us webpack to simple files like: webpack entry.js bundle.js . but not for my angular app
Let me answer it in general and then specific to your use case.
IN GENERAL:
Webpack
is a module bundler
needs entry and output as minimum
configuration
Where do i configure/list-out all my application code?
You dont configure it but code it. Please read on...
How webpack knows what code/modules to pick up to bundle?
Webpack will look at the code configured for entry and then internally builds its module dependencies (as dependency graph).
How do you declare module dependencies?
In short: by using require("module-or-path-here") or import "module-or-path-here". Do note that the javascript (ES6 a.k.a ES2015) itself has native module support now. Here is a good article on JS modules.
What is dependency graph?
Webpack will start with the code configured for entry and then pick up its immediate dependencies. It then goes to find out the dependencies of those immediate dependencies and so on...
Once the dependency graph is complete, webpack will start processing them and bundle them into output.filename located at output.path
Fine, but i want to perform some resource (JS / CSS / SCSS / images, etc..) specific work for ex. minify js code. How to do that?
Webpack is flexible (and powerful) and allows to configure resource specific work via loaders and plugins.
IN SPECIFIC:
The modules in AngularJS (i.e. 1.x) are not same as the modules that webpack works with. As you can see, while declaring the modules in angularJS, you are defining modules with angular by calling angular.module.
One option is to make sure to bundle all your angular module definition files (i.e that consists of angular.module("module-name-here", ["depenndencies"])) first followed by the angular components that needs those modules. There are several way to do that. For ex. name all your angular modules declaration files with a common pattern and then configure webpack to pick them up first.
Minification is pretty simple to achieve with webpack. You can try one of the options pointed out in the webpack documentation.
I'm working in a project where we want to integrate Webpack into our workflow. The problem is, we have over 1000 AngularJS files and adding import/export to all of them in one go is not an option for us. We'd like to bundle all of them and slowly incorporate the import/exports as we work on each file over time.
How would you approach that problem? Any specific best practices when doing this?
We literally had the same problem. Essentially you want to create "entry point files" that perform requires for all your files, since this is how webpack works (it follows the dependency tree). Then point webpack at these "entry point files".
The example at the link above uses TypeScript, but you can easily use ES5 like this:
# ./entry-points/feature1.js
importAll = function(r) {
r.keys().forEach(r);
};
importAll(require.context('./app/feature1', true, /module\.js$/));
importAll(require.context('./app/feature1', true, /(^(?!.*(spec|module)\.js).*\.js)$/));
You can grab a polyfill for Object.keys here, and Array.forEach` here.
Then point to this file from your webpack config like this:
entry: {
'feature1': './entry-points/feature1.js'
}
You can read more details here
I am following the React-router docs, but I have encountered an obstacle that is not really related to the router itself: Babel transpiles the {import} as require, which would be used by Express or Node.js on the server, but from what I understand from the docs, it is actually intended for client-side rendering.
Of course, the JSX file with the router transpiled using Babel and included into a HTML browser page does not work, since require is only used by express/node server-side.
May I ask how is it actually supposed to work in the browser?
Thank you
Babel's transpile of import produces code relying on CommonJS require, you're correct.
You're also correct that node offers a natire require implementation, whereas browsers do not.
There are tools - such as webpack, browserify, and requirejs (among others,) which each do at least two things:
to package up source into a single bundle
to expose that source in a way that satisfies require to match node, allowing you to use the same code at either side.
To that end, what you need to do is to pair babel with one of the packaging tools.
Webpack is more powerful; browserify is easier to use.
Here's a tiny gulpfile where I've automated the process. The relevant source clip is this:
gulp.task('browserify', ['babel'], function() {
var browserifyConfig = {},
bpack = browserify(browserifyConfig, { 'debug' : !production });
return bpack
.require('./dist/pbar.es5.js', { 'expose' : 'pbar' })
.bundle()
.on('error', errorHandler)
.pipe(source('pbar.es5.js'))
.pipe(gulp.dest('./dist'));
});
In order for commonjs like require statement to work in a browser environment. You will need to look into a bundling solution like:
https://webpack.github.io/
http://browserify.org/
A bundler will statically parse your commonjs files and their dependencies to create a bundle which can be used in the browser.
Internet is full of great examples on how they work.
Browserify is easier to get started than Webpack, however I would suggest you learn Webpack over Browserify. Webpack provides you much much more than just loading JS files with its extensive loaders, for example you can do something like:
const imgSrc = require('images/test.svg')
magical right?
I'm trying to figure out how to make my unit tests in my reactJS ES6 application. My application is already using es6 module system, transpiled with jspm/babel to systemJs.
I found babel-jest as preprocessor but even with it, I can't run my tests because jest can't find SystemJs. ("System is not defined" error is shown in the console)
In the browser, as explained in jspm documentation, SystemJs is loaded globally. I guess I should load SystemJs inside my preprocessor, but How can I make systemJs available for loading additional modules in my tests?
Thanks in advance
Unfortunately, Jest does not support SystemJS ES6 modules at the moment.
See the following comments:
So it sounds like jest assumes that your modules resolve based on the Node resolution algorithm.
Unfortunately this isn't compatible with SystemJS's resolution algorithm.
If there was a way in jest to set a "custom resolver" algorithm through an API then we could plug jspm into jest, but I'm not sure if this is currently possible.
-- Comment by Guy Bedford, creator of SystemJS, Jun 2015
It is unlikely there'll be official support for [SystemJS] unless it is a community contribution.
-- Comment by #cpojer, Jest Collaborator, Jan 2016
Also see the following issue: Invalid URL is thrown when requiring systemjs in jest test cases
in essence to get Jest to play nice with an app running on JSPM/SystemJS you need to "teach" it about all the mapping it holds in the config.js file (or however you call System.config())
the long answer is that you need to create an entry for each dependency you have installed with JSPM like this:
//jest configuration
moduleNameMapper: {
...
"^redux$": "redux#3.6.0",
...
}
for each alias you have, you need at least one entry:
moduleNameMapper: {
...
"^common\\/(.*)": "<rootDir>/src/common/$1", //for a dir alias
"^actions$": "<rootDir>/src/actions/index", //for a file alias
...
}
you also need to have these mappings in your nodeNameMapper:
moduleNameMapper: {
...
"^npm:(.*)": "<rootDir>/jspm_packages/npm/$1",
"^github:(.*)": "<rootDir>/jspm_packages/github/$1",
...
}
and finally, you need to have this moduleDirectories config:
moduleDirectories: ["node_modules", "jspm_packages/npm", "jspm_packages/github"]
this isnt really practical because you dont want to keep two copies of all your dependencies registry and have to sync them when they change...
so the short and better answer, you use my gulp-jest-jspm plugin :)
even if you dont use gulp, you can use its getJestConfig() method to generate the config for you before you run Jest.