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.
Related
I have been trying to build my gatsby (react) site recently using an external package.
The link to this package is "https://github.com/transitive-bullshit/react-particle-animation".
As I only have the option to change the props from the components detail, I cannot read/write the package file where it all gets together in the end as it is not included in the public folder of 'gatsby-build'.
What I have tried:
Editing the package file locally, which worked only on my machine but when I push it to netlify, which just receives the public folder and the corresponding package.json files and not the 'node-modules folder', I cannot make netlify read the file that I myself changed, as it requests it directly from the github page.
As a solution I found from a comment to this question, we can use the "Patch-Package" to save our fixes to the node module and then use it wherever we want.
This actually worked for me!
To explain how I fixed it: (As most of it is already written in the "Patch Package DOCS), so mentioning the main points:
I first made changes to my local package files that were giving the error.(For me they were in my node_modules folder)
Then I used the Patch Package Documentation to guide my self through the rest.
It worked after I pushed my changes to github such that now, Patch Package always gives me my edited version of the node_module.
When dealing with third-party modules that use window in Gatsby you need to add a null loader to its own webpack configuration to avoid the transpilation during the SSR (Server-Side Rendering). This is because gatsby develop occurs in the browser (where there is a window) while gatsby build occurs in the Node server where obviously there isn't a window or other global objects (because they are not even defined yet).
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /react-particle-animation/,
use: loaders.null(),
},
],
},
})
}
}
Keep in mind that the test value is a regular expression that will match a folder under node_modules so, ensure that the /react-particle-animation/ is the right name.
Using a patch-package may work but keep in mind that you are adding an extra package, another bundled file that could potentially affect the performance of the site. The proposed snippet is a built-in solution that is fired when you build your application.
I have a create react app, and I have two requirements that I am trying to achieve:
1 Language management for index.html:
When a user visits my-app/any/subpath?lng=en or my-app/any/subpath they should be served index_en.html which links to bundle.js
When a user visits my-app/any/subpath?lng=de they should be served index_de.html linking to the same bundle bundle.js
This requirement is pretty easy. I can solve it by serving my frontend with something like NGINX and selecting the html document by the query string lng. However, the hard part is getting this functionality in my local React development environment, which is my second requirement below:
2 I want to achieve this in my local dev environment, preferrably keeping Webpack Dev Server, so that I don't loose the benefits of hot reloading and automatic rebuilding on react code changes.
What I have done so far:
It seems that Create React App does not support this by default, so I have ejected through npm run eject. I build index_en.html and index_de.html from a base html document as a part of npm run start/build commands. To build several html documents, I had to modify the webpack.config.js as so:
const languages = ["en", "de"]
...
module.exports = function(webpackEnv){
...
return {
plugins: [
...otherPlugins,
...languages.map(lng=> new HtmlWebpackPlugin({
inject: true,
template: path.resolve(appDirectory, `public/index_${lng}.html`),
filename: `index_${lng}.html`,
...(isEnvProduction ? productionConfig : {}),
}))
]
}
}
This produces index_en.html and index_de.html the way I want, both linking to bundle.js.
Now the issue is that if I run npm run start, they are both served at the same path, so the Webpack Dev Server doesn't know which one to serve. I want to select between them based on a query parameter ?lng=de. Is this even possible with the webpack dev server? And what are my options?
I have also tried putting the localized index.html's into separate folders per language. E.g. public/de/index.html, but if I access myapp/de/some/subpath I will still be served the root index.html (english).
I decided to try out WebPack on a new project I'm spinning up today and I'm getting really strange behavior from the sourcemaps. I can't find anything about it in the documentation, nor can I find anyone else having this issue when skimming StackOverflow.
I'm currently looking at the HelloWorld app produced by Vue-CLI's WebPack template -- no changes have been made to the code, the build environment, or anything.
I installed everything and ran it like so:
vue init webpack test && cd test && npm install && npm run dev
Looking at my sourcemaps, I see the following:
This is a hot mess. Why are there three version of HelloWorld.vue and App.vue? Worse yet, each version has a slightly different version of the code and none of them match the original source. The HellowWorld.vue sitting in the root directory does match the original source, but what's it doing down there instead of in the ./src/components folder? Finally, why isn't there a fourth App.vue that has the original source for it?
As far as I can tell this may have something to do with the WebPack loaders. I've never gotten these kinds of issues with any other bundler, though. Below is an example of the exact same steps using the Browserify Vue-CLI template:
No webpack:// schema, only one copy of every file, the files actually contain the original source code (kind of important for source maps), no unexpected (webpack)/buildin or (webpack)-hot-middleware, no . subdirectory,.... just the source code.
I haven't worked with Vue so can't really describe how exactly this is happening but it seems to be related to Vue Loader. Looking at the documentation I did not really find anything that clarifies why it would create three different files for one component. But it does seem logical considering that a .vue file might contain three types of top-level language blocks: <template>, <script>, and <style>.
Also, looking at two of those files you do see a comment at end of each file that suggests it was modified in some way by a Vue loader. Either this
//////////////////
// WEBPACK FOOTER
// ./node_modules/vue-loader/lib/template-compiler
or
//////////////////
// WEBPACK FOOTER
// ./node_modules/vue-style-loader!./node_modules/css-loader
The third file is different but it still does have code that identifies it as being modified by Vue loader. Here is some of that code
function injectStyle (ssrContext) {
if (disposed) return
require("!!vue-style-loader...")
}
/* script */
import __vue_script__ from "!!babel-loader!../../node_modules/vue-loader/..."
/* template */
import __vue_template__ from "!!../../node_modules/vue-loader/..."
/* styles */
var __vue_styles__ = injectStyle
The document also says this:
vue-loader is a loader for Webpack that can transform Vue components written in the following format into a plain JavaScript module:
Which explains why you might not see the same type of behaviour with other bundlers.
Now, This might not be the answer you were looking for but just wanted to share what I had found.
This is actually a feature of webpack.
webpack has HMR (Hot Module Reloading). If you look in your network tab, go ahead and make an update to your HelloWorld.vue file. You'll see a js chunk come thru as well as an updated JSON manifest. Both of these will have a unique hash at the end for each time you make a change to the application. It does this so the browser does not have to do a full reload.
For a better explanation of this I would highly recommend reading through https://webpack.js.org/concepts/hot-module-replacement/
When I init a react-native project, index.ios.js is created as project entry file.
Can I change this file's name and if so, how?
When you start a react-native app you'll see this message output by the React Packager:
Running packager on port 8081
and then:
Looking for JS files in
/Users/gbirman/gil/mapily
React packager ready.
By this point, the packager has compiled your JS files and is serving them with the .js extension renamed to .bundle. For example, your index.io.js file is compiled and served from:
http://localhost:8081/index.ios.bundle
If you added another file foo.js in the same directory as index.ios.js, the packager would serve it from:
http://localhost:8081/foo.bundle
You can confirm this by opening that url in your browser.
Now to answer your question, your project has an iOS/AppDelegate.m file with the following line:
jsCodeLocation = [NSURL URLWithString:#"http://localhost:8081/index.ios.bundle"];
... as you can see, it loads the index.ios.bundle. You can change the path/filename there to whatever you want, but it's probably best to stick with the recommended approach of naming your entry file index.io.js
Suppose you've moved your index.ios.js into a folder called dist. You need to do two things
For your development environment: Update jsBundleURLForBundleRoot in AppDelegate.m to match your updated path.
For your release bundle: Open your Xcode project. You'll need to update the Bundle React Native code and images task under Build Phases for your project. Update the shell script in this section to look like below:
export NODE_BINARY=node
../node_modules/react-native/packager/react-native-xcode.sh dist/index.ios.js
react-native-xcode.sh accepts the ENTRY_FILE as an optional first argument, defaulting to index.ios.js if none is found.
Updated Build Phases Example
Reference - react-native/scripts/react-native-xcode.sh
I'm using MVC5/Durandal and wondering what the recommended approach to bundling/minifying a durandal application would be. Ive seen docs on using Weyland but will be deploying to an Azure Website and don't see how to leverage this in my .net-based deployment process. How can I go about configuring automated bundling/minification of my durandal application when deploying to Azure?
I've spent a bit of time trying to optimize an AngularJS application for one of the biggest banks in Holland. Although it's no Durandal, this might still give you some ideas.
So what did we use for bundling and minification? Out-of-the-box bundling and minifcation from ASP.NET MVC ( which is from the system.web.optimization namespace )
You need to get a couple of things in order to leverage this:
Organize your files
Organize your code files in a way that they can easily be bundled. We had a large tree structure under the /app folder in the web project. Something like:
- App
|- Modules
| |-Common
| | |- Directives
| | |- Templates
| | |- Filters
| --User
| ...
| app.js
So the application skeleton was inside the app.js and all the other JS files were required by the application. Point being: all SPA code is separated from vendor javscript files and the rest of course
Set up the budling inside the bundle configuration
That's a breeze now, just do regular-old-bundling from your Global.asax.cs:
Make sure there's a line in the Application_Start() with:
BundleConfig.RegisterBundles(BundleTable.Bundles);
That calls into your BundleConfig class which only needs 1 bundle to pack up the whole /app folder:
bundles.Add(new ScriptBundle("~/bundles/app")
.Include("~/app/*.js")
.IncludeDirectory("~/app", "*.js", true));
We needed the app.js to load first - therefore we put it explicitly at the top. Don't worry, it will not be requested twice.
For bundling - only the sequence of files can be important. However, through including that file explicitly, we could control that and it worked like a charm.
Minification
Now for minification we had to do some code changes. AngularJS can be used with different types of syntax - some of which can be minified, others give problems.
Example:
angular.module('myapp').controller(function($http,$scope) { ... });
can not be minified. The minifyer will change the name of $http so something shorter, after which the injector cannot do dependency injection anymore, since it only knows stuff called $http and $scope and not the minified variable name.
So for Angular you need to use a different syntax:
angular.module('myapp').controller(['$http', '$scope', function($http,$scope) { ... }]);
With this, the injector will know that the first argument of the function is '$http' because that's the first string variable in the array. OK, but that's Angular and you're looking for Durandal.
I've heard that Durandal uses AMD right? So within a module, minification shouldn't be a problem, because it should be smart enough. However, if you're using external things, you want to make sure everything still works. I've read here that you'll want to use te following syntax for your AMDs:
define("someModule", ["jquery", "ko"], function($,ko) { ... });
And that gave us a reduction of 80% of the requests and around the same number for the Javascript payload.
Added AngularJS bonus
This might not be of interest to you, but maybe for other readers. The reason we didn't get a 99% reduction of requests is because AngularJS uses something called 'directives'. These are like HTML templates. Those HTML templates still needed to be downloaded every time they were used.
They were also included in our /app folder - hence we had to add an IgnoreRoute in the routeconfig:
routes.IgnoreRoute("app/");
I Googled, but couldn't find anything similair for Durandal. So Angular will go and get all of the small HTML files, but will first check its $templatecache. In case the HTML content is not in the cache, it goes out and downloads it and places it in the cache, so it needs to be downloaded only once.
We, well I, wrote a T4 generator that outputs a JS file in which all the HTML files in the /app folder are added to the $templatecache. So the output would look like:
angular.module('myapp').run(function($templateCache) {
/// For all *.html files in the /app folder and its children
$templateCache.put('...filename...', '...content of html file ...');
});
Because this .JS file was inside the /app folder, it would immediately get bundled with the application, no more configuration required. This got our requests down for the whole application to just 1. Since the amount of HTML was quite small, it seemed to be faster to do 1 larger request, then multiple smaller ones.
Point is: if Durandal has something similair and it will look for some templates, find the caching mechanism ( because it will have it ) and try to tap into that.
Controlling bundling and minification
I'll quote this site: http://www.asp.net/mvc/overview/performance/bundling-and-minification
Bundling and minification is enabled or disabled by setting the value
of the debug attribute in the compilation Element in the Web.config
file. In the following XML, debug is set to true so bundling and
minification is disabled.
<system.web>
<compilation debug="true" />
</system.web>
So for your release build - this flag shouldn't be set and thus bundling + minification should happen.
But of course, you will want to test locally - you can either remove this from your web.config or override it with BundleTable.EnableOptimizations = true;
Deployment to Azure
Then you mention deployment to Azure. I don't know how this would be any different from deploying to a local server. We used web-deploy. Bundling and minification doesn't happen build-time, so there are no changes in the build process. Also, the optimization framework is being deployed with the site - so no difficult things for deployment either.
Maybe one thing though: you could consider adding the CDN for the libraries you are using:
bundles.Add(new ScriptBundle("~/bundles/jquery", "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js")
In case the CDN location of jQuery was already cached by the client's browser, you'll save another request.
Measuring the performance was easy: just open up the network tab on Chrome and reload the page ( make sure it's not caching ). Check the total number of requests and the total amount of data downloaded. Like I said: we saw a huge improvement.
Well, hope it helps or points you in a right direction.
The below answers are pretty complicated. I've just gone through this with a simple(r) approach here:
https://lifelibertycode.wordpress.com/2015/04/14/how-to-bundle-up-your-mvc-durandal-app/
The steps below:
Step 1: Install Node
Step 2: Install Gulp
$ npm install --global gulp
$ npm install --save-dev gulp
Step 3: Create your gulpfile.js
This should be at the root of your project, and should initially contain this:
var gulp = require('gulp');
gulp.task('default', function() {
// place code for your default task here
});
Step 4: Install gulp-durandal
npm install gulp-durandal --save-dev
Step 5: Update your gulpfile.js
var durandal = require('gulp-durandal');
gulp.task('durandal', function(){
durandal({
baseDir: 'app', //same as default, so not really required.
main: 'main.js', //same as default, so not really required.
output: 'main.js', //same as default, so not really required.
almond: true,
minify: true
})
.pipe(gulp.dest('dir/to/save/the/output'));
});
Step 6: Add a post-build event to your project
if '$(Configuration)'=='Release' (
cd $(ProjectDir)
gulp durandal
)
Step 7: Add a pre-build event to your project
I needed this because occasionally gulp would hang when generating the new main-built.js on top of an existing version. So I just delete the old version before the build begins:
if '$(Configuration)'=='Release' (
cd $(ProjectDir)/app
del main-built.js
del main-built.js.map
)
Now, when you build your project, you’ll generate a new main-built.js file each time that can be served down to your clients. Sweet.
At this point, you probably have some concerns.
How do I keep my files un-bundled when I’m debugging?
#if (HttpContext.Current.IsDebuggingEnabled) {
<script type="text/javascript" src="~/Scripts/require.js" data-main="/App/main"></script>
} else {
#Scripts.Render("~/Scripts/main-built")
}
Where ‘main-built’ is defined in your BundleConfig:
bundles.Add(new ScriptBundle("~/Scripts/main-built").Include(
"~/app/main-built.js"));
How do I bust cache when I have new stuff to ship?
If you’re using the above approach, bundling will take care of this for you. ASP.NET will detect a change to your main-built.js file and append a unique identifier to your bundles to bust the cache.
What if my client has downloaded my SPA, and then I ship an update. Won’t the (outdated) client-side code stick around until they refresh?
Yup. Unless you leverage build versioning to tell the client when it’s out of date, and then tell the user.
I happen have written a blog post about this:
https://javascriptkicks.com/articles/4230
Hopefully that helps you out