Make Webpack output files relative to the input files - javascript

Let's assume I want my compiled JavaScript files to exist side-by-side with my source files, resulting in a directory structure like:
- TimeframeToolbar
- TimeframeToolbar_compiled.js
- TimeframeToolbar_src.js
- dependencies
- *contains js files that are imported by TimeframeToolbar_src.js*
Is it possible to do this with Webpack? From what I can tell, the output path only allows a single directory, meaning that the source and compiled file trees must be totally separate.

The trick is to make the keys of your entry configuration object the path you want for the output files. For example:
entry: {
'feature-1/feature-1': './dev/feature-1/feature-1.jsx',
'feature-2/feature-2': './dev/feature-2/feature-2.jsx',
},
output: {
filename: '[name].js',
path: './build',
}
This will result in the following compiled files:
./build/feature-1/feature-1.js
./build/feature-2/feature-2.js
So essentially the [name] placeholder in output.filename ends up being a directory path rather than just a file name.

Related

__webpack_public_path__ does not work after reloading the page

We are working on a Vue.js application which is built with webpack. The requirement is that our application not only has to be accessible via the base path / but also via a custom path, so that the application could be accessable next to other services. With webpacks \__webpack_public_path__ I was able to set the base path on the fly regarding a specified base path, like if the current path has got /foo/ in it, the base path should start at .../foo/.
While navigating through the application everything looks good, as long as I open the app at the base path. The problem is that after I navigate to any sub path and reload the page, no files can be found. The server will first provide the index.html and there I need to use relative paths, since the base path must be determined dynamically. But if any other than the base path is opened, the relative paths in the index.html won't point to the correct bundle.js and the \__webpack_public_path__ will not be set...
Currently we have got two entry points in our webpack config. The first one is a JS file where we the global variable \__webpack_public_path__ will be set relatively based on the current visited URL. So lets say the base path should start at /foo/ and the visited URL is https://www.host.com/some/path/foo/sub/sub1. Therefore the relatively base path will be /some/path/foo/ and assets will be found at i.e. /some/path/foo/assets. All other paths used in the webpack config, like in the file-loader or any other plugin, are relative.
// webpack.config.js
...
module.exports = (env, argv) => ({
...
entry: ['#babel/polyfill', './src/main/js/constants/webpack-public-path.js', './src/main/js/index.js'],
output: {
filename: 'assets/js/bundle.js',
path: path.resolve(__dirname, relativeOutputPath),
publicPath: '/'
},
module: {
...
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'file-loader',
options: {
name: 'assets/fonts/[name].[ext]'
}
}
...
},
...
});
// webpack-public-path.js
__webpack_public_path__ = (() => {
const BASE_PATH = '/foo/';
let path = window.location.pathname;
return path.includes(BASE_PATH) ? path.substring(0, path.indexOf(BASE_PATH) + BASE_PATH.length) : '/';
})();
Has anyone ever faced a similar problem? Is it possible, that the relative paths in the index.html can be defined afterwards or maybe are defined at build time by webpack?
I got a solution for my problem. What I had to do was to load all necessary assets manually in the index.html. Unfortunatly I have to maintain the determination of the dynamic base path on two different files (index.html and the webpack-public-path.js) but at least it's working now. So in the index.html I insert respective tags into the DOM manually and therefore load all needed assets based on the determined base path.

Dynamic import in Webpack: it is possible to distribute chunks between subfolders?

Note: this question about chunks, not output bundles.
If we need to distribute webpack output bundles between multiple subpaths, we can do it next way (unusual, but I use absolute paths):
const WEBPACK_CONFIG = {
// ...
entry: {
'open/js/testOpenEntryPoint': 'C:/.../example.loc/source/open/3_es6/testOpenEntryPoint',
'admin/js/testAdminEntryPoint': 'C:/.../example.loc/source/admin/3_es6/testAdminEntryPoint'
},
output: {
path: 'dest',
filename: '[name].js',
chunkFilename: '[name].js'
}
}
However, it does not work for chunks: chunkFilename, unlike filename, ignores subpath and outputs chunks in single directory. Nevertheless, can we distribute chunks between multiple subpaths as shown below?
Currently I know only multi-compilation solution, but maybe it is more simple way.
📁 source
 📁 open
  📄 testOpenEntryPoint.js
  📁 dyn_load
   📄 dynForTestOpenEntryPoint.js
 📁 admin
  📄 testOpenEntryPoint.js
  📁dyn_load
   📄 dynForTestAdminEntryPoint.js
📁 dist
 📁 open
  📄 testOpenEntryPoint.js
  📁 dyn_load
   📄 0.js
 📁 admin
  📄 testOpenEntryPoint.js
  📁dyn_load
   📄 1.js

In Webpack, how to get multiple outputs with a single entry main.js(having multiple css files inside files)?

My directory structure should be like.
|-src/
| |-styles/ (less)
| | |-xx.less(input inside main.js)
| | |-yy.less(input inside main.js)
| | |-zz.less(input inside main.js)
|
|-dist/
|-assets/
| |-xx.css(output should be like this)
| |-yy.css(output should be like this)
| |-zz.css(output should be like this)
and my main.js file contains,
require('./styles/xx.less');
require('./styles/yy.less');
require('./styles/zz.less');
and my entry point is
entry: {
app: './main.js'
},
1. How can I get output as chunks(xx.css,yy.css,zz.css)?
2. Tried extractTextPlugin there I was able to get output in the name of app.css but not as I wanted.
Which plugin I can try to extract output as in same name and number of input I have in main.js file?
You can separate your css requires into files and in the entry point to them.
for example:
xx.less.js
require('./styles/xx.less');
and in webpack entry:
app: [path.join(__dirname, 'path/to/xx.less.js')]
and call webpack several times using node script or something
More elaborate answer:
every entry in the webpack config represent the bundled file that will be created, the entry point to the start point js file and every css file will be created according to the reference of the css in that js file.
So if you want several css files you need several entries in your webpack config and every js in the entry will require its less file and in that way you will get 3 js file and 3 css files so your config should look something like this:
{
entry: {
xx: [ path.resolve(__dirname, 'path/to/js/xx.js')],
yy: [ path.resolve(__dirname, 'path/to/js/yy.js')],
zz: [ path.resolve(__dirname, 'path/to/js/zz.js')]
},
output: {
path: path.resolve(__dirname, 'dist/assets'),
filename: '[name].js' //the placeholder name will be replace by the entry name (xx,yy,zz)
}
...
plugins: [
new ExtractTextPlugin({
filename: '[name].css' //this is the name of the css according to the entry in the js file
})
}
Your less loader should stay the same and just point to the src/styles where all the less files are and in your javascript files (xx.js,yy.js,zz.js) you should require the corresponding less file
in xx.js you call xx.less: require('./styles/xx.less');
in yy.js you call yy.less: require('./styles/yy.less');
in zz.js you call zz.less: require('./styles/zz.less');
And when you run webpack he will 3 css files (and 3 js files...)

Browserify adding unwanted directories

Setting up gulp for the first time. I've got it correctly compiling the files, it's just sticking them in the wrong place, and I can't quite figure out what to change to get it right.
After they compile, I have it adding the .conveyor.js suffix and then I want it to place them in the /scripts directory. But it's placing them in /scripts/src/js/ — it's adding a couple subdirectories. The raw dev files themselves are in src/js/ directories in a separate location, but I don't want that to carry over. Here's my gulp setup:
module.exports = function() {
var files = [
'./src/js/dashboard.js',
'./src/js/pages.js',
'./src/js/poll.js'
];
var tasks = files.map(function(entry) {
return browserify({
entries: [entry],
paths: ['./node_modules', './src/js/']
})
.bundle()
.pipe(source(entry))
.pipe(rename({
extname: '.conveyor.js'
}))
.pipe(gulp.dest('../scripts/'));
});
return es.merge.apply(null, tasks);
};
The way I understand it, "files" are all of the files it looks for to compile. "paths" allow you to specify directories that your require statements can be relative to so you don't have to do a bunch of period-forwardslashing. and then "dest" is where you want the files to end up. But I'm clearly misunderstanding something.
The offender is here
.pipe(source(entry))
entry is set to the exact path you are using for the files path. Hence the duplication.
source() in this isn't the source of the file, but ends up being the file that gets created.
You would want to modify the object to provide just the file name as the entry and the source path is separated. Also, you can drop the rename method, I think.

how to minify a whole folder content using grunt.js

Instead of mention every js seperatly,
is this the way to minify and concatinate a whole js folder?
module.exports = function(grunt) {
grunt.initConfig({
min: {
dist: {
src: ['scripts/*.js'],
dest: 'dist/built.min.js'
}
}
});
};
Yes, that's correct if you only want to concatenate and minify all .js files in the scripts directory one level deep.
For example, if scripts/ contains a.js and b.js and the foo/ directory, you'd get the concatenation and minified result of a.js + b.js but nothing in the foo/ directory.
What if you want to get everything in the foo/ directory (and all other nested directories) as well? Change the expression from ['scripts/*.js'] to ['scripts/**/*.js'] -- or any minimatch expression:
https://github.com/gruntjs/grunt/blob/master/docs/api_file.md#gruntfileexpand
You're able to use any minimatch expression since the grunt min task uses the expandFiles function:
https://github.com/gruntjs/grunt/blob/master/tasks/min.js#L21
The downside to using a minimatch expression with this task is it's hard to understand what order the files will be concatenated in, which is often very important. Be careful if this matters.
Also, please note that a new version of grunt (0.4) is coming out very soon. This will make this answer obsolete, as the min task has been changed in 0.4 (but will still support minimatch expression).
If your folder consist only js files you are right but if your folder have nested folders such as, foo is our main js folder in which we have another nested folder loo and inside it we also have some js files such as :
foo:
mu.js
su.js
loo:
ku.js
wu.js
In this case you have to modify your code in such manner :
module.exports = function(grunt) {
grunt.initConfig({
min: {
dist: {
src: 'foo/**/*.js',
dest: 'dist/foo.min.js'
}
}
});
};
by doing in such a way you can minimize your all js files of foo folder even nested folder files too. I suggest cocat js files before minimizing.

Categories