webpack: transpiling file so out put is next to the source file - javascript

I am using webpack to turn my ts in js. I want the js files to be placed at the same location as their ts sources. right now I am 'cheating' by having many entry points. the entry points are the path to the file.
here is the snippet of my config
entry: {
'path/to/my/file':'path/to/my/file.ts',
'other/path/to/other/file':'other/path/to/other/file.ts'
},
output: {
path: rootFolder,
publicPath: outputFolderName + '/',
filename: '[name].js'
}
this currently works. I was wondering if there was a cleaner way to do this. Some way of not depending on having the name of the entry point be the path so that the entry points are more flexible.

You are using wrong tool for this job. Webpack is bundler, it is designed to bundle many files into single package.
What you want to do is to compile Typescript into Javascript. Use typescript compiler for that. Just use/run tsc.
Just make sure outDir in tsconfig.json is equal . or absent at all.
You might need to install it globally for ease of use
npm install -g typescript

Related

Combine, Minify, and convert to ES5 with WebPack and Babel

I have a project that works perfect and was written in TS, I had to convert it to plain JS and it works for the most part. The issue where I am struggling is removing the default WebPack loader after the files have been combined and minified, WebPack includes a loader to the final output even thought I do not need a loader since all the files are combined into one large file.
+ filea.js
+ fileb.js
+ filec.js
+ filed.js
-> output bundle.js
I have read a few articles/posts that recommend manually creating a config file providing the name of each of the files that will combined and minified, this may work OK but the problem is that the project I am working on is broken into small chunks (modules) so that tools such WebPack can be smart enough and know when a file should be added as a dependency in the final output.
I know we can combine and minify multiple individual JS files but when it comes to exporting a single file it seems like the task is trivial With TS but in the vanilla JS world there is little or no information about the subject.
I don't understand something, do you want to have one big file or small individual modules (chunks)?
An example of small modules:
module.exports = {  
entry: {    
app: './src/app.js',
admin: './src/admin.js',
contact: './src/contact.js'  
}
};
Another method is one main module and it contains all smaller modules.
module.exports = {  
entry: {    
app: './src/app.js'  
}
};
You can also use something like lazy loading. Then the modules (chunks) will be dynamically loaded only when needed. lazy-loading
Here is an example of using several entries webpack-boilerplate.
Sounds like you have a project with several JS files and you want to use webpack to bundle all of them and minify the result.
Webpack was built for this.
You'll need to add a build step in your package.json like this:
"scripts": {
"build": "webpack --config prod.config.js"
}
Then you'll need to create a webpack.config.js with a module.exports block that has an entry point and rules to include in your project. The following should be a minimal setup that can get your started:
const path = require('path');
module.exports = {
entry: "./your/path/to/src",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
module: {},
plugins: [
new MinifyPlugin(minifyOpts, pluginOpts)
]
}
You can add modules that perform additional code transpilation for files that matcha a certain regex. You can also use a plugin to perform minification such as babel-minify-webpack-plugin as documented here https://webpack.js.org/plugins/babel-minify-webpack-plugin/. (Note you will need to add this dependency.)
The full webpack configuration can be found here: https://webpack.js.org/configuration/

Webpack using Typescript: Common settings in both configs, so which take precedence?

I am in the initial stages of converting a javascript (with webpack) project into a typescript project and one of the many confusions I have is that their appears to be some configuration settings that can appear in webpack and typescript, so which takes precedence?
(I'm currently working on a node cli application).
Eg, the primary example is which files are included in compilation.
In webpack config, you can specify which input files are selected with rules:
module: {
rules: [
{
test: /index.ts/,
use: 'shebang-loader'
},
{
test: /\.ts(x?)$/,
use: 'ts-loader'
},
{
test: /\.json$/,
use: 'json-loader'
}
]
},
As you can see from above, I'm using various loaders for different file types.
Then my initial tsconfig.json is as follows:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"noImplicitAny": true,
"lib": [
"es5", "es2015", "es6", "dom"
]
},
"include": [
"lib/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
So what is the true nature of the interaction between webpack and typescript? I have not been able to discern this from typescript or webpack documentation. Both appear to be able to specify the input files that are included in compilation.
Another (probably better example) is the output file. In webpack config I have the following:
output: {
libraryTarget: 'commonjs',
path: path.join(__dirname, 'dist'),
filename: 'application-bundle.js'
}
which defines 'application-bundle.js' is the output file inside the 'dist' folder.
In the tsconfig, you can have something like the following:
"outFile": "./dist/application-bundle.js",
(I currently do not define an outFile property, but I know you can do so, but in being able to do so, brings up ambiguities and hence confusion). So in this scenario, does webpack override typescript or vice-versa? What is the recommended strategy?
There are probably more typescript/webpack crossovers that are going to cause confusion, but the 2 that I have described so far are the most upfront and pressing issues I need to understand, thanks.
EDIT: Having thought about it, I also need another clarification. I am guessing when you build a TS/WP project, the TS compiler runs first creates all the .js files (let's say in the .dist folder). Then webpack bundles all the generated .js files. So assuming this is correct, do I then need to configure webpack to use as its input the .js files in the dist folder instead of the .js files inside the project source (ie everything under ./lib which is where my source js files are)?
I was hoping to convert my project in an incremental manner so what I have just said does not really fit my needs. Webpack would need to pick up some .js files from ./dist and some files from ./lib which have not yet been converted to typescript. I don't know how to modify the project for incremental upgrade.
[...] there appears to be some configuration settings that can appear in webpack and typescript, so which takes precedence?
You are right on the point that there is some natural redundancy in the configuration when Webpack is combined with TypeScript. Lets pick up your first question:
which files are included in compilation? [...] Another example is the output file. [...] So in this scenario, does webpack override typescript or vice-versa? What is the recommended strategy?
Simply spoken, both TypeScript and Webpack process/transform input files and emit the output in a target directory structure or file bundle(s) - both need some input/output configuration info. TypeScript compiler can run on its own, and also be integrated as file processor as part of a bigger Webpack build. With outFile option TypeScript can even be seen as a mini-bundler on its own, as it bundles all .ts-files to a single target file.
To answer the question, if TypeScript or Webpack configuration takes precedence, it is important to understand, how Webpack works. I'll quote one of your assumptions here:
I am guessing when you build a TS/WP project, the TS compiler runs first creates all the .js files (let's say in the .dist folder). Then webpack bundles all the generated .js files.
That is not quite correct. But good you said that, as it sheds more light on your core understanding problem. Everything in Webpack starts with the entry point you specify in the config - if you will, that's the input. From this entry module, webpack considers all other transitively imported modules (e.g. via import or require) and creates a dependency tree.
Every file in the dependency tree can optionally be transformed by Loaders, which can also be chained like a file processing pipeline. So ts-loader and the underlying TypeScript compiler apply transformations for .ts/.tsx files with test: /\.ts(x?)$/ predicate.
All in all you see, that Webpack considers your entry file, which leads to a bunch of further imported .ts/.tsx files (amongst your other file types, we neglect them here). And for each single file, the TypeScript loader will be invoked in the course of the loader processing pipeline. Therefore, it is inherent that TypeScript I/O config will be ignored and Webpack's entry/output configuration takes precedence in the build. All other TypeScript related settings are taken from tsconfig.json, as described in the ts-loader docs: "The tsconfig.json file controls TypeScript-related options so that your IDE, the tsc command, and this loader all share the same options."
I was hoping to convert my project in an incremental manner
It is perfectly fine to migrate from JavaScript to TypeScript in a stepwise manner!
Hope, that helps.

Compiling typescript path aliases to relative paths for NPM publishing?

I have a typescript project that uses paths for imports. For example:
"paths": {
"#example/*": ["./src/*"],
}
Thus the project can import files directly from using statement like:
import { foo } from "#example/boo/foo";
For publishing to NPM I have I'm compiling the typescript files and then copying the result to a dist folder. Thus all the *.d.ts and corresponding *.js files are in the dist folder. I also copy package.json to the dist folder.
I now test this by generation a new typescript project and then run npm i -S ../example/dist, in order to install the project and attempt to run some of the compiled typescript code.
However the relative imports no longer work. For example if boo.ts depends on foo.ts it will say that it can't resolve foo.ts.
When I look at the *.d.ts files they contain the same paths that were used the source code before it was compiled. Is it possible to turn these into relative paths?
Update
I looks as if generating relative paths for Node is something Typescript does not perform automatically. If you would like this feature, as I would, please provide feedback on this bug report.
As a brief follow-up to arhnee's suggestion, it seems that as of Aug 2020, Microsoft still refuses to implement custom transformers for whatever reason, so these modules remain relevant.
So to future readers, here's how you can actually compile TS path aliases to relative paths. ttypescript is merely a transformer framework that requires a "path transformer" in order to actually convert the TS path aliases. Thus you will need to install both ttypescript and typescript-transform-paths.
npm i --save ttypescript typescript-transform-paths
Then, it's easy as just specifying usage by adding the following property to the compilerOptions object in tsconfig.json:
"plugins": [
{ "transform": "typescript-transform-paths" }
]
And finally, run ttsc instead of tsc.
There is a project called ttypescript that you can use for this. If you use it with the module typescript-transform-paths I beleive it will acheive what you want.

How to bundle a library with webpack?

I want to create a frontend library.
Therefore I want to use webpack. I especially like the css and image loader.
However I can only require non-JS files if I am using webpack.
Because I am building a library, I cannot garanty that the user of my library will too.
Is there I way to bundle everything into a UMD module to publish it?
I tried using multiple entry points, however I cannot require the module then.
You can find good guide for creating libraries in Webpack 2.0 documentation site. That's why I use ver 2 syntax in webpack.config.js for this example.
Here is a Github repo with an example library.
It builds all files from src/ (js, png and css) into one JS bundle which could be simply required as an umd module.
for that we need to specify the follow settings in webpack.config.js:
output: {
path: './dist',
filename: 'libpack.js',
library: 'libpack',
libraryTarget:'umd'
},
and package.json should have:
"main": "dist/libpack.js",
Note that you need to use appropriate loaders to pack everything in one file. e.g. base64-image-loader instead of file-loader
The comment written by #OlegPro is very helpful. I suggest every one to read this article for explanation of how these stuff work
http://krasimirtsonev.com/blog/article/javascript-library-starter-using-webpack-es6
You need the following for sure if you want to be able to import the bundle file in your project
output: {
path: path.resolve(__dirname, myLibrary),
filename: 'bundle.js',
library: "myLibrary", // Important
libraryTarget: 'umd', // Important
umdNamedDefine: true // Important
},

Using Webpack and stylus to create static css

new to Webpack. I was thinking about migrating JS part of my application to it. However, I don't like the way it handles CSS. Would like to keep it easy and link them on my own. Unfurtunately documentation wasn't very helpful, same with the search results.
So, what do I need exactly?
Stylus compilation from lots of .styl files to static .css.
There will be three static stylesheet files (entry points?), but completely different from entry points of JS part of an application.
Also some "watch" feature, which would compile css when one of source .styl files has been changed.
Is there somebody who could point me in right direction, maybe write a config? Is this even possible with Webpack or should I stay with Grunt?
Thanks for any useful answer.
To learn more about the details of Webpack you can refer to this online book SurviveJS - Webpack, which will walk you through most of concepts related to Webpack.
To accomplish what you need you can start by creating webpack.config.js in the root of your project and it can be like this:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './entry.js', // you application entry point
output: {
filename: 'bundle.js', // resulting bundle file
path: './public' // the output folder path
},
module: {
loaders: [
{
test: /\.styl$/,
loader: ExtractTextPlugin.extract("style", "!css!stylus") // plugin used to extract css file from your compiled `styl` files
}
]
},
plugins: [
new ExtractTextPlugin('style.css') // output css bundle
]
};
Then require your stylus files in you entry.js file require('./style.styl');
Don't forget to install required loaders and plugins
npm install --save-dev css-loader sass-loader style-loader extract-text-webpack-plugin

Categories

Resources