Typescript in `file://` environment - javascript

Recently I just picked up Typescript for a personal project. Since the project is designed to be ran locally (explicitly file://), I won't be able to use import/export features due to CORS restrictions. Aware of another similarly written question but lacking the specific context on my use case, I pose these questions:
How does one tell Typescript that all (or at least certain) scripts are imported to HTML via <script type="text/javascript" src="./source.js">?
Does Typescript's tsc build projects with this in mind? Also, does it edit existing HTML files to take this into consideration too? If not, are there tools to automate this process as well?
I don't want to bundle them like webpack or tsc-bundle does, since a secondary objective to this project is to keep all .js files human-readable just as much as the .ts files do.
Building Typescript using tsc -p tsconfig.json, configured to "target" : "ES2015" and "module" : "None", only outputs their respective .js files and doesn't update any of the HTML's <script> includes. Am currently maintaining the html file by manually inserting and juggling any new modules that emerges over the course of development.
My current load order in index.html is as follows:
index.js handles UI controls and loads first.
The remaining pseudo-modules .js files loads in-between, since these only define classes and doesn't perform any operations, so I figured it's safe to load them here.
main.js handles all the code from javascript "modules" and loads last.
My main concern is that my in-between modules might load out of order due to human error.
Edit: Running a local webserver is out of the question too, since the project is meant to target audience with limited technical knowledge, with the index.html file the only file they need to run in their browser.

Related

Importing Locally Installed Node Modules in TypeScript

Scenario:
I'm developing a script using TypeScript (version >= 3). My script has features which dependend upon a well-known graphics library, which itself is written in JavaScript. I have installed this library and its TypeScript type definitions locally in my project, resulting in the relevant files being placed in the appropriate sub-directories of the "node_modules" directory.
I have my project set up to transpile my TypeScript to ES6-specification JavaScript.
I have an import statement at the top of my main TypeScript file of the form:
import * as LIB from 'library'
Where "library.js" is the required library file, burried somewhere in the sub-directories of "node_modules". The TypeScript compiler has its own complex process of module resolution which means that it can find this file without requiring a relative filepath or a file extension.
If I run the TypeScript compiler on my main ".ts" file, I get a JavaScript file out. Because I'm using ES6, the import statement in the generated JavaScript file is identical to the one in my TypeScript source. This is my issue.
The file that the generated JavaScript is attempting to import cannot be found by the script when it runs on my local development server, because the file it is trying to import is somewhere inside the "node_modules" directory and the import is not pointing to that directory. As such, an error along the lines of Error resolving module specifier is shown in the browser console when the code is executed.
I want the code to transpile from TypeScript to JavaScript (ES6) in such a way that the imports in the generated JavaScript can be resolved when I serve my code to a browser from a local test server.
Question:
1) Is this behaviour a result of my improperly configuring the TypeScript compiler?
2) Is this behaviour something that results from or is influenced in a direct way by the properties in the "tsconfig.json" and/or "package.json" configuration files?
3) Is this actually a problem, or is it all caused by my not understanding how files should be organised and served from a Node server?
Thanks in advance for your help.
While you say you are running the code "on a node-based server", your error message suggests that you are actually serving an ES6 module containing a non-relative import like import * as LIB from 'library' to a browser. As you suggest, that isn't supported because the resolution algorithm for non-relative imports in browsers hasn't been standardized yet; see, for example, this article. Either you would need a separate tool to rewrite the non-relative import to a relative import (I'm not familiar with such tools but would invite others to describe them in other answers) or you would need to switch from browser native modules to a non-native module bundler or loader such as Webpack, Rollup, Browserify, or RequireJS, any of which should support your scenario.
At the time of writing, it looks like my problem cannot be solved (in a general way) without using a module bundler or loader as suggested by #Matt McCutchen. Here's a couple of discussions of the issue on the TypeScript GitHub page: 1, 2.
For others finding this question in future, I solved the problem in my specific case a very unsatisfactory way - by avoiding using imports at all, and simply loading the requied library in a HTML script tag before I loaded my main dependent script. This is only acceptable because my project has a single dependency which will not be updated (so I won't ever have to change the "src" in the script tag manually).
I emphasise again, this is not a satisfactory solution in the general case, so I will leave the question open for a while in case anyone comes up with a better answer.

How do you handle bower components properly when it comes to references, concat, and minify?

I recently started an endeavor on creating a VSTS Extension. I utilized bower to automatically pull in the latest vss-web-extension-sdk component, and everything works fine so far. One thing that bothers me is that I had to reference the script in the following way:
<script src="bower_components/vss-web-extension-sdk/lib/VSS.SDK.min.js"></script>
I understand that I can change the bower components directory, but should it be a unique name or can it be scripts, which is the folder where my own scripts reside?
Additionally:
Should I (and how do I) concatenate components together when it comes to production?
Should I minify all of my components (Javascript) together, even though I'm already provided *.min.js files?
I've come across other similar questions relating to this, but I'm not utilizing Grunt or Gulp, just npm and bower. I ask this because I want to ensure that my production code does not identify which tooling I used (npm, bower), and I want the production code to be as proper as possible, which may require me to minify all JS together (I'm not sure on this one)?

Keep Flow types post webpack build

I want to add Flow to my current project I am working on. Everything works really great. However, I couldn't find a way of someway keep the types post build. I am using a monorepo structure and I have a lot of NPM modules. I would like to get an error if a module changes it's interface or it's exported functions/classes/types changes.
Any ideas/guidance is highly welcomed!
Thanks!
Webpack bundles JS files into a single output file, it has no way do preserve Flow types in the output bundle.
If you want to preserve Flow logic for use alongside this bundle, the current best practice would be to include your original sourcecode as .js.flow files. This blog post elaborates on this approach, but the short version is, you'd use flow-copy-source to output a bunch of .js.flow files that match your original source code.
If you insist on others including your compiled bundle instead of the source files, you'll need to include a .js.flow file that provides all of the external type interfaces. Here's the interface file for Immutable.js as an example.
Unless your library has some sort of build complexity that requires the distribution of its compiled assets, I would just rely on the consumers of your lib to compile and strip types on their own.

Does web essentials offer a way to use the bundled js file in production but individual js files in development?

The Setup:
I have a large SPA app using many JavaScript files that are bundled using Web Essentials bundling in Visual Studio 2013. I then include the minified js files generated by Web Essentials on my HTML page. This application does not use ASP.NET
The problem:
I would like to be able to distribute the HTML page with a single minified script referenced for production but the individual unminified scripts for development.
Reasons:
The minified scripts even with the map files make it difficult to debug. Variable and parameter names have been minified and thus the debugger does not match the source. Additionally, since everything is in one file, its hard to look at for development.
Current solution:
I have a grunt task that goes into my html file and modifies it such that the <script> tags are replaced. This has the con of growing with every file I add to the page.
Does web essentials offer a better solution than what I am currently doing that I might have simply overlooked?
You are mixing the bundling tool with the reference implementation.
Web Essentials 2013 builds bundles of compressed (minified) JavaScript, CSS, LESS, SASS and image files. Web Essentials should create the minified bundle regardless whether you are in Debug mode.
You are looking for a way to selectively reference minfied files in Release mode and originals in Debug. That may mean rather involved Razor coding to check for release version and render reference calls.
A better solution is to use ASP.NET Bundling and Minification.
It's easy to debug your JavaScript in a development environment (where the compilation Element in the Web.config file is set to debug="true" ) because the JavaScript files are not bundled or minified when debug="true"
The minified bundle will still exist if debug="true" in your Web.config. But at run-time, the framework will reference the originals files instead of the minified. Your Web.config is now responsible for maintaining which version of your assets are referenced.
Web Essential bundles are passive assets. There is no functionality in Web Essentials to distinguish between Release and Debug mode because that is a run-time action.
Note: Web Essentials 2015.0 has removed bundling and minification.
Important!
Web Essentials 2015 no longer contains features for bundling and
minifying of JS, CSS and HTML files as well as compiling LESS, Scss
and CoffeeScript files. Those features have been moved to their own
separate extensions that improves the features greatly
The common practice is to use the ASP.NET Bundler. This is another reason to get away from bundling with Web Essentials.
i ma not sure if Web-essentials can handle that scenario though
As per my current project experience below are the things i use to debug the code locally while development-
For local debugging if you are using the ASP.NET bundling feature and must have specified the file references in the BundleConfig.cs. You can enable the browser to Load each file as is by Setting the flag BundleTable.EnableOptimizations=true; in the Global.asax file. And we load the single bundle file to work on local environment
For Production we use the minified versions of the file references.
eg in your HTML you can have a check like this
#if(local){
#Scripts.Render("~/Scripts/src/BundleName");
}
else{
//Which is an partial HTML which contains the minified file references
Html.RenderPartial("ClientTemplates/MinifiedScripts");
}
Thanks
I have just used the Bundler/Minifier from here: https://github.com/madskristensen/BundlerMinifier
To help see the unbunded and unminified JS and CSS I have created a helper to render both depending on whether the web application is running with debug enabled.
see: https://bundlerminifierhelper.codeplex.com/
Example:
#Html.Bundle("/Content/Styles/Site.min.css")
#Html.Bundle("/Scripts/Scripts.min.js")
Note: Using relative paths, including the forward slash (/)
When debugging all the input files will be rendered out to the page, and when not debugging, the supplied path will be rendered out.

What is the best practice to consolidate multiple Javascript files?

For CSS, I can use SASS to import one CSS file to another and produce only single CSS file. What is the similar method for Javascript files?
You might want to check out Closure Compiler (which is a Google product).
You would probably want the Closure Compiler Application form of the product.
A sample workflow would probably look like:
Create a list of your JS files and paths
Run the command to compile and concatenate files (java --jar compiler.js --js path_to_file1.js --js path_to_file2.js (etc.) compiled.js)
Closure Compiler also has a related project, Closure Stylesheets, that does the same thing for stylesheets.
This approach, of course means that there's a pre-compilation step. Depending on your backend, there also exist libraries that do the compilation when the page is built. For example, for JSP, there's Granule a tag library that creates the compiled JS and CSS files at page build.
There's a third possibility: modularization. Since you gave the example of being able to import CSS files in SASS, an analogue for JavaScript is using a module library, using either the CommonJS standard, or (the one I prefer), the AMD (asynchronous module definition) pattern, which I have personally used with RequireJS. RequireJS also comes with a nice optimizing tool that will bundle up (minify, compress, concat etc) all the required files for your application
UPDATE
Since you mentioned that you are using Django in the comments (might be useful to update the question with this info too), see if this answer helps too
You could use minify which allows you to minify and combine javascript files. It also works with CSS.

Categories

Resources