This is just something I thought today and I didn't see a lot of information so I'm going to share this weird cases and how I personally solved them (if there's a better way please comment, but meanwhile this might help others ^^)
In a regular module, you would do something like this to export your function/library/object/data:
// regular NodeJS way:
module.exports = data;
// ES6 way
// (will get transpiled to the regular way using the module variable by webpack)
export data;
default export data;
When compiling the library usually babel or tsc are used, but if for any reason you want not only to compile (transpile) your library but also pack it using webpack, you will encounter this case.
As you know, in a webpack bundle the module variable is local to the bundle (every module/file gets wrapped with a function where module is a parameter = local variable), so nothing really gets exported outside the bundle, is just nicely managed by webpack.
That means that you can't also access the contents using the regular require/import methods.
In some case you might find necessary to export outside webpack. (i.e. you are trying to build a library using webpack and you want it to be accessible by other people). This basically means you need to access the original module variable, but webpack doesn't expose it like it happened with __non_webpack_require__.
See also: Importing runtime modules from outside webpack bundle
The solution is to create our own __non_webpack_module__ (as webpack does with __non_webpack_require__.
How I did it is using webpack.BannerPlugin to inject some code outside the bundle. This code is prepended to the build after the minification is done, so it's preserved safely.
In your webpack.config.js:
plugins: [
new BannerPlugin({
raw: true,
banner: `const __non_webpack_module__ = module;`,
}),
]
And again, if you are using TypeScript, in global.d.ts:
declare const __non_webpack_module__: NodeModule;
And now, you can do something like this in your code:
__non_webpack_module__.exports = /* your class/function/data/whatever */
This will allow to import it as usual from other files
Tip: You might want to look at BannerPlugin to check other options, like include or exclude so this variable is only generated on the desired files, etc.
I'm working on a Single Page App developed in Vue.js hosted on a node.js server.
At the moment it is still under development but eventually it will be exposed to external customers, and since we will deal with sensitive data we would like to avoid to have the .vue files and the relative file-tree structure visible when users inspect the element in devtool.
See attached screenshot as a sample that shows the files I would like to hide.
Is there a way to achieve that?
I was able to make webpack export the SPA in a bundle by playing around with the config file.
In the file ./config/index.js I have changed the following flags:
build: {
// other code...
devtool: '', // Previously it was set as '#source-map'
productionSourceMap: false, // Previously it was set as true
cssSourceMap: false, // Previously set as true
// other code...
}
I've found the solution by reading the webpack documentation where it explains what the settings do: https://webpack.js.org/configuration/devtool/#production
Thanks everyone for putting me in the right direction.
It seems you are running on development mode of vue. And Of course files will be visible by then. When shipping a Vue SPA, it should be build and compiled into chunks of JS.
You can build a production version of your spa by running.
npm run build
This will produce 1 folder and 1 file inside the dist
--dist
----static
----index.html
When this were served. No .vue files will be visible anymore.
And when you check it on Browsers Dev tools. It should look more like of this
The folders node_modules, src, and theme should be a level up in the folder structure. Therefore, you have to modify your paths pointing to those files.
The app.js can be in that folder only with files that are JS executables.
Maybe I'm trying to do something silly, but I've got a web application (Angular2+), and I'm trying to build it in an extensible/modular way. In particular, I've got various, well, modules for lack of a better term, that I'd like to be able to include or not, depending on what kind of deployment is desired. These modules include various functionality that is implemented via extending base classes.
To simplify things, imagine there is a GenericModuleDefinition class, and there are two modules - ModuleOne.js and ModuleTwo.js. The first defines a ModuleOneDefinitionClass and instantiate an exported instance ModuleOneDefinition, and then registers it with the ModuleRegistry. The second module does an analogous thing.
(To be clear - it registers the ModuleXXXDefinition object with the ModuleRegistry when the ModuleXXX.js file is run (e.g. because of some other .js file imports one of its exports). If it is not run, then clearly nothing gets registered - and this is the problem I'm having, as I describe below.)
The ModuleRegistry has some methods that will iterate over all the Modules and call their individual methods. In this example, there might be a method called ModuleRegistry.initAllModules(), which then calls the initModule() method on each of the registered Modules.
At startup, my application (say, in index.js) calls ModuleRegistry.initAllModules(). Obviously, because index.js imports the exported ModuleRegistry symbol, this will cause the ModuleRegistry.js code to get pulled in, but since none of the exports from either of the two Module .js files is explicitly referenced, these files will not have been pulled in, and so the ModuleOneDefinition and ModuleTwoDefinition objects will not have been instantiated and registered with the ModuleRegistry - so the call to initAllModules() will be for naught.
Obviously, I could just put meaningless references to each of these ModuleDefinition objects in my index.js, which would force them to be pulled in, so that they were registered by the time I call initAllModules(). But this requires changes to the index.js file depending on whether I want to deploy it with ModuleTwo or without. I was hoping to have the mere existence of the ModuleTwo.js be enough to cause the file to get pulled in and the resulting ModuleTwoDefinition to get registered with the ModuleRegistry.
Is there a standard way to handle this kind of situation? Am I stuck having to edit some global file (either index.js or some other file it references) so that it has information about all the included Modules so that it can then go and load them? Or is there a clever way to cause JavaScript to execute all the .js files in a directory so that merely copying the files it would be enough to get them to load at startup?
a clever way to cause xxJavaScriptxx Node.js to execute all the .js files in a directory:
var fs = require('fs') // node filesystem
var path = require('path') // node path
function hasJsExtension(item) {
return item != 'index.js' && path.extname(item) === '.js'
}
function pathHere(item) {
return path.join('.', item)
}
fs.readdir('./', function(err, list) {
if (err) return err
list.filter(hasJsExtension).map(pathHere).forEach(require) // require them all
})
Angular is pretty different, all the more if it is ng serve who checks if your app needs a module, and if so serves the corresponding js file, at any time needed, not at first load time.
In fact your situation reminds me of C++ with header files Declaration and cpp files with implementation, maybe you just need a defineAllModules function before initAllModules.
Another way could be considering finding out how to exclude those modules from ng-serve, and include them as scripts in your HTML before the others, they would so be defined (if present and so, served), and called by angular if necesary, the only cavehat is the error in the console if one script tag is not fetched, but your app will work anyway, if it supposed to do so.
But anyway, it would be declaring/defining those modules somewhere in ng-serve and also in the HTML.
In your own special case, and not willing to under-evalute ng-serve, but is the total js for your app too heavy to be served at once? (minified and all the ...), since the good-to-go solution may be one of the many tools to build and rebuild your production all.js from your dev js folder at will, or like you said, with a drag&drop in your folder.
Such tool is, again, server-side, but even if you only can push/FTP your javascript, you could use it in your prefered dev environment and just push your new version. To see a list of such tools google 'YourDevEnvironment bundle javascript'.
To do more with angular serve and append static js files under specific conditions, you should use webpack so the first option i see here is eject your webpack configuration and after that you can specify what angular should load or not.
With that said, i will give an example:
With angular cli and ng serve any external javascript files you wanna include, you have to put them inside the scripts array in the angular-cli.json file.However you can not control which file should be included and which one not.
By using webpack configuration you can specify all these thing by passing a flag from your terminal to the webpack config file and do all the process right there.
Example:
var env.commandLineParamater, plugins;
if(env.commandLineParamater == 'production'){
plugins = [
new ScriptsWebpackPlugin({
"name": "scripts",
"sourceMap": true,
"filename": "scripts.bundle.js",
"scripts": [
"D:\\Tutorial\\Angular\\demo-project\\node_moduels\\bootstrap\\dist\\bootstrap.min.js",
"D:\\Tutorial\\Angular\\demo-project\\node_moduels\\jquery\\dist\\jquery.min.js"
],
"basePath": "D:\\Tutorial\\Angular\\demo-project"
}),
]}else{
plugins = [
new ScriptsWebpackPlugin({
"name": "scripts",
"sourceMap": true,
"filename": "scripts.bundle.js",
"scripts": [
"D:\\Tutorial\\Angular\\demo-project\\node_moduels\\bootstrap\\dist\\bootstrap.min.js"
],
"basePath": "D:\\Tutorial\\Angular\\demo-project"
}),
]
}
then:
module.exports = (env) => {
"plugins": plugins,
// other webpack configuration
}
The script.js bundle will be loaded before your main app bundle and so you can control what you load when you run npm run start instead of ng-serve.
To Eject your webpack configuration, use ng eject.
Generally speaking, when you need to control some of angular ng-serve working, you should extract your own webpack config and customize it as you want.
I created a project using ng.
I called ng eject to get a webpack.config.js.
I added pug to the webpack.
I want to pass the data from src/environments/environment.ts to pug but I can't figure out how to require the typescript file from a normal javascript file.
I can always change environment.ts to a json file or javascript file but would like to leave it the way it is.
Here is the environment.ts file
export const environment = {
production: false,
title: 'My App DEV'
};
As long as it is actually valid JavaScript (not TypeScript), as your example is, then yes. You'll just need to include/require it including the extensions:
require('./environment.ts');
// or
import environment from './environment.ts';
If it were to contain TypeScript code, you'd need to transpile it to regular JavaScript at some point. Where/when/how you do that would be up to your build pipeline.
Given an (Angular-)Webapp with a Webpack-buildprocess I would like to add several build-targets to my Webpack configuration.
There are plenty tutorials on how to modify your webpack.config at compile time, which is already helpful (and probably all I need) to get dev and prod builds running.
However I was hoping that there is a way to parametrize the build process so that different files are used for the build-process.
Question
How do i configure Webpack to replace all *.js/ *.html-Files with files called *.mobile.js/ *.mobile.html (if available) during the build-step?
Bonusquestion:
How do I exclude environment-specific import statements via webpack-config?
Example
I got several view/controller-pairs which are linked via Angulars $stateprovider. In the mobile version of the webapp most of the HTML-views should be a mobile-optimized template.
If I use several entry-points for webpack to generate a desktop-version and a mobile-version I would have to rewrite every file where HTML-Files are required or imported for each of my build-targets and specify the new filenames manually.
This would cause a lot of code-duplication and is hard to maintain.
I ended up using the following in my webpack.config
const target = env && env.mobile ? 'mobile' : 'desktop'
resolve: {
extensions: [`.${target}.js`, '.js', `.${target}.html`, '.html']
}