I'm hosting a Nuxt site on AWS S3 w/ Cloudfront, so when deploying I need to invalidate the CloudFront CDN. This means it takes a bit for the deploy to
I'd like to console.log(buildHash) when the application starts. What's the best way to do this?
I could add this to a plugin, but what's the best way to get the build hash?
There is a manifest.xxx.js file which seems to hold build hashes of the other files in the project. Is that manifest hash unique for each unique build?
Thanks!
This is a bit of a tumbleweed. Here's what I did:
A plugin to print the manifest hash:
```
// Statup and small stuff
window.onNuxtReady(() => {
// Print build version of this script
var scripts = window.document.getElementsByTagName('script')
for (var i=0; i < scripts.length; i++) {
// Get the script name
var src = scripts[i].src
src = src.substr(src.lastIndexOf('/') + 1)
if (src && src.startsWith('manifest')) console.log('Hello ' + src)
}
})
```
Added to nuxt.config.js
```
plugins: [
'plugins/bootstrap-vue.js',
'plugins/scroll.js',
{ ssr: false, src: '~plugins/etc.js' },
]
```
Related
Hello & Happy New Year!
I am facing a problem in my Quasar (v1) app in regard to environment variables. I don't want to solve this using dotenv or any other Node package as these are no longer the recommended way to use environment variables in Quasar.
So I have some local environment variables I am setting/using, following the documented best practice on the Quasar official docs:
quasar.conf.js:
build: {
env: {
EXAMPLE: ctx.dev
? JSON.stringify('https://dev.')
: JSON.stringify('https://prod.')
},
This allows me to specify a different endpoint in dev and prod as I would expect, but not ideal for a few obvious reasons.
index.vue:
console.log(process.env.EXAMPLE,'<---API')
I get the expected output of my mock API endpoint. Good.
Now CloudFlare Workers' variables are globally scoped (No process.env object), so once configured in wrangler.toml, it should be possible to simply call them by name:
wrangler.toml:
[vars]
CFEXAMPLE = "example_token"
BUT this does not work (I cannot get my Quasar application to build if I include this as follows). Probably because CFEXAMPLE is not defined in my quasar.conf.js
quasar.conf.js:
build: {
env: {
CFEXAMPLE: CFEXAMPLE
},
I also cannot console.log CFEXAMPLE from my index.vue file either (but I CAN build my app and deploy to CloudFlare OK).
What is the best way to get environment variables working correctly across CloudFlare and localhost please?
Thanks
Ok so thanks to Michal for the hint. In the end I did this:
Firstly create an environment.js.
environment.js:
module.exports = {
dev:{
NODE_ENV: 'development',
PROXY_URL: 'xx',
}
},
prod:{
NODE_ENV: 'production',
PROXY_URL: 'zz',
}
}
}
Next import it and include a function to return the correct environmental var.
quasar.conf.js:
const config = require('./src/boot/environment.js')
module.exports = function(ctx) {
const getEnvVar = p => {
if (ctx.dev) return (config.dev[p])
else return (config.prod[p])
}
...
Finally add environment variables to env:
quasar.conf.js:
env:{
PROXY_URL:JSON.stringify(getEnvVar('PROXY_URL')),
POST_TO:JSON.stringify(getEnvVar('POST_TO')),
FIRESTORE_CREDS:JSON.stringify(getEnvVar('FIRESTORE_CREDS')),
},
I have a VUE2 project and in the public folder I created an iframe.html file that will be loaded in an iframe.
That iframe will also load a javascript.js file that I want encoded/uglified upon "npm run build" but I also want to be able to access it during dev.
How could I proceed?
Should this js file be placed inside the /src/assets/ folder and referenced from the iframe.html file? If yes, any advice?
Or should it stay in the public folder and upod the dist folder being built, encode it with something.
Any solution is welcome, thanks in advance!
Edit: Here are further details of how I use the iframe.
First, I'm referencing the .vue file in the router like so:
{
path: "/pages/:id/edit",
name: "edit",
component: () => import("../views/Edit.vue"),
},
Next, in the Edit.vue file, I add the iframe like so (note how it's referencing iframe.html that is in the public directory):
<iframe
id="iframe"
ref="iframe"
src="iframe.html"
/>
Next, in the iframe.html it's just normal html code, with this part including the javascript.js file (that actually is in the public folder as well for now)
<script src="javascript.js"></script>
You can explicitly include the .js file in your Webpack config by adding a rule for UglifyJsPlugin:
npm i -D uglifyjs-webpack-plugin
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
...
module.exports = {
optimization: {
minimizer: [
new UglifyJsPlugin({
include: /\/regex-for-file/,
minimize: true
})
]
}
...
};
In Vue.config.js, this might look like:
configureWebpack: {
plugins : [
new webpack.optimize.UglifyJsPlugin({
uglifyOptions: {
include: /\/regex-for-file/,
minimize: true
}
)}
]
}
Another option is to use uglify-es; this would allow you to get even more explicit by specifying from where to copy the file during build (assuming you might want the file located outside of src/):
npm i -D uglify-es // CopyWebpackPlugin ships w/ Vue's Webpack conf by default
const UglifyJS = require('uglify-es');
const { resolve } = require('path');
const resolveAbs = (dir) => resolve(__dirname, dir);
new CopyWebpackPlugin([
{
from: resolveAbs('../external'),
to: config.build.assetsSubDirectory
},
{
from: resolveAbs('../src/custom-build-path'),
to: config.build.assetsServerDirectory,
transform: (content, path) => UglifyJS.minify(content.toString()).code;
}
]),
To be able to access it during dev, you can include the path of the js file (relative to your Vue src directory) using the resolve.alias option in the config (so you don't need to deal with possibly ridiculous relative paths in your project). Finally, you can look into webpack's HTML plugin docs for info on importing an external index.html file if needed
I would recommend not putting it in static; by default it will not be minified and built if placed in that directory.
Update/edit: Sorry, I saw a 'uglify' and just assumed you wanted uglify js. As long as the script is in your Vue project directory (or otherwise specified in the Webpack config) the file should be minified during build. Vue has pretty smart defaults for Webpack; assuming the iframe is being referenced somewhere in the app i.e. the dependency graph it will be built.
My Vue CLI project relies on JSON data from the backend. Because of CORS issues I copied that file into the project's public folder which works during development. But for the deployment builds I'd like to get rid of that file.
How can I exclude that file from the build process? I suppose the chainWebpack method in vue.config.js is the key but I can't find how to tweak the different outputs for serve and build.
I got this to work:
module.exports = {
chainWebpack: config => {
if (process.env.NODE_ENV === "production") {
config.plugin("copy").tap(opts => {
opts[0][0].ignore.push({ glob: "someFile.json" });
return opts;
});
}
}
};
The process.env.NODE_ENV === "production" makes the exclusion only apply to the build output.
I´m trying to setup a build workflow using the aforementioned technologies, but I´m getting the following error, which seems very generic upon running tests on karma:
TypeError: 'undefined' is not an object (evaluating 'a.Sifter=b()')
This happens even without adding any ECMSA6 specific feature. The same workflow works fine without the transpiling phase in the workflow.
What I tried was to set the babeljs after a concatenation phase and before executing a uglifying on it, like the following snippet:
var defaultTasks = [
"sass:prod", // compile scss sources
"cleanAll", // clean folders: preparing for copy
"copyAll", // copying bower files
"cssmin:customVendor", // minify and concat 'customized from vendor' css
"concat:vendorStyles", // concat vendors's css + minified 'customized from vendor' and distribute as 'css/vendor.css'
"uglify:rawVendors", // minifies unminified vendors
"concat:vendorScripts", // concat vendors's scripts and distribute as 'scripts/vendor.js'
"ngAnnotate:app", // ng-annotates app's scripts
"concat:appScripts", // concat app's (customized from vendor's + ng-annotated + customer's)
"babel",// uses babeljs to convert brandnew ES6 javascript into ES5 allowing for old browsers
"uglify:app" // minify app script and distribute as 'scripts/app.js'
];
if (!skipTest) {
defaultTasks.push("karma:target"); // run tests on minified scripts
}
The imporant definitions are shown:
babel: {
options: {
"presets": ['es2015']
},
dist: {
files: {
"<%= concat.appScripts.dest %>": "<%= concat.appScripts.dest %>"
}
}
},
uglify: {
options: {
mangle: {
except: [
"jQuery", "angular", "tableau", "LZString", "moment", "Moment", "Modernizr",
"app", "modules"
]
}
},
app: {
files: [{
src: ["<%= concat.appScripts.dest %>"],
dest: "<%= app.dist %>/scripts/app.js"
}]
}
},
I´ve tested the transpile a bit, running the default logic from babel url, and it works well, converting basic stuff.
Is there any better workflow that I could use to still run the tests against the same code that would be executed for real?
Thanks
In the end, the workflow was correct.
I just need to modify the filesets a bit in order to avoid transpiling the selectize.js file (which wasn´t really needed).
However, not sure why it was breaking
That solved to me, so I´m closing the question, but perhaps might be useful for someone else.
I've recently downloaded VS15 CTP-6 to get the feeling of how to develop the next generation VS projects, but having trouble figuring out the development flow I should be following with this separation of code and wwwroot.
The way I understand it is this (Angular project):
Develop views, css and js.
Use grunt tasks to uglify and copy css and js to wwwroot folder.
Browse wwwroot as a local IIS site to see the changes.
When wwwroot is ready for production, copy its content.
But if I find a problem during step 3, how can I find its origin given that the js and css are minified ?
Surely I'm wrong, so should I create another copy of wwwroot for development, without the minification?
You should use grunt task to uglify/minify your code when you're ready to go in production
And use an other grunt task to copy your code when you're in dev
Or you can use uglify with 2 target: 1 to uglify and 1 to beautify:
module.exports = function (grunt) {
grunt.initConfig({
bower: {
install: {
options: {
targetDir: "wwwroot/lib",
layout: "byComponent",
cleanTargetDir: false
}
}
},
uglify: {
ugli_target: {
files: {
"wwwroot/scripts/chat.js": ["Scripts/chat.js"]
}
},
beauty_target: {
options: {
beautify: {
beautify: true
},
mangle: false,
sourceMap: true
},
files: {
"wwwroot/scripts/chat.js": ["Scripts/chat.js"]
}
}
}
});
// This command registers the default task which will install bower packages into wwwroot/lib
grunt.registerTask("default", ["bower:install"]);
// The following line loads the grunt plugins.
// This line needs to be at the end of this this file.
grunt.loadNpmTasks("grunt-contrib-uglify");
grunt.loadNpmTasks("grunt-bower-task");
};