I'm attempting to get a gruntfile working to concatenate / uglify javascript files in a Laravel application. All of my tasks work in isolation, but for whatever reason the paths to my input javascript files are not being set correctly.
Here's an example of one of my blade templates:
#section('scripts')
<!-- build:js /js/min/page.min.js -->
<script type="text/javascript" src="/js/scrollIt.min.js"></script>
<script type="text/javascript" src="/js/jquery.omniwindow.js"></script>
<script type="text/javascript" src="/js/isotope.min.js"></script>
<!-- endbuild -->
#stop
Here's my useminPrepare / usemin task definitions:
useminPrepare: {
html: 'app/views/**/*.blade.php',
options: {
dest: 'app/views/dist'
}
},
usemin: {
options: {
assetDirs: [ 'public/js' ]
},
html: [ 'app/views/dist/**/*.blade.php' ]
},
I have no defined uglify task, I'm just relying on the one that usemin will generate.
All templates are making it into the 'app/views/dist' directory correctly, with the correct replacement (in the example above, there's a single javascript file at public/js/min/page.min.js being included in the template). During processing, I noticed output:
$ grunt build
Running "useminPrepare:html" (useminPrepare) task
Going through {list of templates} to update the config
Looking for build script HTML comment blocks
Configuration is now:
concat:
{ generated:
{ files:
[ { dest: '.tmp/concat/js/min/page.min.js',
src:
[ 'app/views/course/js/scrollIt.min.js',
'app/views/course/js/jquery.omniwindow.js',
'app/views/course/js/isotope.min.js' ] },
] } }
uglify:
{ generated:
{ files:
[ { dest: 'app/views/dist/js/min/page.min.js',
src: [ '.tmp/concat/js/min/page.min.js' ] },
] } }
cssmin:
{}
As you can see above, it is looking for my javascript files in app/views/course/js directory, which is incorrect. Why is this? I thought specifying assetDirs: ['public/js'] in my usemin task would tell grunt where to find those files. I have tried changing the script references to look like this:
<script type="text/javascript" src="../../../public/js/scrollIt.min.js"></script>
And this causes a successful build, but breaks my local development so its definitely not a solution. Do I need to somehow override the uglify:generated task, and if so, how do I do it for multiple different templates with generated filenames?
If it's necessary, you can see the entirety of my Gruntfile.js here. You can see from there I had to also add a new copy task for copying Javascript files from app/views/dist/js/min back over to public/js/min. I'd also like to get rid of that, but if I can just get around this issue I'd be happy.
The answer here actually turned out to be relatively simple, and was able to be gathered directly from the usemin documentation (as soon as I started to look hard enough):
Blocks are expressed as:
<!-- build:<type>(alternate search path) <path> -->
... HTML Markup, list of script / link tags.
<!-- endbuild -->
In my case for working with Laravel, I needed to specify an alternate search path of public/ and it wound up working just fine:
#section('scripts')
<!-- build:js(public/) /js/min/script.min.js -->
<script type="text/javascript" src="/js/script1.js"></script>
<script type="text/javascript" src="/js/script2.js"></script>
<script type="text/javascript" src="/js/script3.js"></script>
<script type="text/javascript" src="/js/script4.js"></script>
<!-- endbuid -->
#stop
Related
I have a script from a third party, that I need implemented on my Nuxt site in the Header.
What would be the best way to insert a script such as this?
<script id="sleeknoteScript" type="text/javascript">
(function (){
var sleeknoteScriptTag=document.createElement("script");
sleeknoteScriptTag.type="text/javascript";
sleeknoteScriptTag.charset="utf-8";
sleeknoteScriptTag.src=("//sleeknotecustomerscripts.sleeknote.com/00000.js");
var s=document.getElementById("sleeknoteScript");
s.parentNode.insertBefore(sleeknoteScriptTag, s);
})(); </script>
<!-- End of Sleeknote signup and lead generation tool - www.sleeknote.com -->
Usually I would put scripts in Nuxt.config like this.
script: [
{ src: 'https://unpkg.com/#lottiefiles/lottie-player#0.2.0/dist/lottie-player.js' },
]
But this one I don't know.
You can do it in the same way, just place the script into a javascript file and use the path to that file as a script's src property value in the nuxt.config.js:
script: [
{ src: '/scripts/myScript.js' },
]
The myScript.js would be placed in static/scripts/myScript.js in this case
I have a vue project created with vue-cli. The normal output when running yarn build is a dist folder with an index.html and a js and css sub-directory with the corresponding .js and .css files.
I want the build output to be a single html file that contains the js and css.
I added a vue.config.js file in the root of my project and set it to output a single js file and that is working ok. But I want to only have a single html file with the js and any css already on the html file.
module.exports = {
css: {
extract: false,
},
configureWebpack: {
optimization: {
splitChunks: false
}
}
}
Basically I want my html file to be something like this:
<html lang=en>
<head>
... meta tags
<title>my title</title>
</head>
<body>
<div id=app></div>
<script>
// contents of the output js file here
</script>
</body>
</html>
Is this possible?
Using Vue 3.9.3
Someone answered with a suggestion to look into html-webpack-inline-source-plugin but removed their answer. But that was exactly what I needed to get this done.
The plugin is not Vue or Vue-CLI specific but it works if you do the following:
1) Add a vue.config.js file in the root of the app.
2) The linked plugin above is actually an extension of another package. You need both.
npm install --save-dev html-webpack-plugin
npm install --save-dev html-webpack-inline-source-plugin
3)
// vue.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin')
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
module.exports = {
css: {
extract: false,
},
configureWebpack: {
optimization: {
splitChunks: false // makes there only be 1 js file - leftover from earlier attempts but doesn't hurt
},
plugins: [
new HtmlWebpackPlugin({
filename: 'output.html', // the output file name that will be created
template: 'src/output-template.html', // this is important - a template file to use for insertion
inlineSource: '.(js|css)$' // embed all javascript and css inline
}),
new HtmlWebpackInlineSourcePlugin()
]
}
}
4) Add a template. This is necessary for working in the Vue context because without this the output html file by default won't have the necessary <div id="app"></div> and Vue won't mount to anything. I basically took the normal output html file and modified it a little.
<!-- output-template.html -->
<!DOCTYPE html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta http-equiv=X-UA-Compatible content="IE=edge">
<meta name=viewport content="width=device-width,initial-scale=1">
<title>example title</title>
</head>
<body><noscript><strong>We're sorry but my example doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript>
<div id=app>
</div>
<!-- plugin will insert js here by default -->
</body>
</html>
Then build like normal and the output.html file will be in the /dist folder
Is it possible to take code from an external JS file, then paste it inline into script tags (in index.html), once the application is built?
For example, both files below are intended to be identical but I'd like the JS to be implemented externally in the src/dir and inline within the build/dir:
src/index.html
<head>
<script src="long/minified/code.js"></script>
</head>
build/index.html
<head>
<script>
// long... minified code to be added inline here
</script>
</head>
long/minified/code.js
(function(){var this,isSomeLong='minifiedCode';})();
Gruntfile.js
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
dist: {
src: [
'long/minified/code.js',
],
dest: 'build/index.html',
}
});
It's possible I'm completely off and need something like grunt-include-source
You can use grunt-processhtml to easily inline your scrips:
HTML
<head>
<!-- build:js inline -->
<script src="long/minified/code.js"></script>
<!-- /build -->
</head>
Gruntfile task:
grunt.initConfig({
processhtml: {
dist: {
files: {
'build/index.html': ['src/index.html']
}
}
}
});
I have a grunt tasks to concat and minify all my javascript files into one single file and the javascript file is in dist folder. "dist/<%= pkg.name %>.min.js'"
"Gruntfile.js"
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
concat: {
options: {
separator: ';'
},
dist: {
src: ['src/main/resources/app/js/**/*.js',
'src/main/resources/app/config/*.js',
'src/main/resources/app/app/js'],
dest: 'dist/<%= pkg.name %>.js'
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
},
dist: {
files: {
'src/main/resources/app/dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask("default", ["concat", "uglify"]);
};
Now, how can I use this minified version of javscript? Moreover, my index.html entry point of my code points to the non-minified version.
"index.html"
<div ui-view/>
<script data-main="config/require-conf" src="vendor/requirejs/require.js"></script>
You could use usemin from https://www.npmjs.com/package/grunt-usemin. Usemin, with other tasks as
concat
uglify
cssmin
filerev
is able to minify all js and css in one single file. You only need to add a build:js as you can see in snippet below:
<!-- build:js SCLogic.min.js -->
<!-- Load app main script -->
<script src="app/app.js"></script>
<!-- Load services -->
<script src="app/services/authInterceptorService.js"></script>
<script src="app/services/authService.js"></script>
<script src="app/services/blablaService.js"></script>
<!-- Load controllers -->
<script src="app/controllers/indexController.js"></script>
<script src="app/controllers/homeController.js"></script>
<script src="app/controllers/loginController.js"></script>
<script src="app/controllers/blablaController.js"></script>
<script src="app/directives/validNumber.js"></script>
<script src="app/controllers/angular-locale_es-es.js"></script>
<!-- endbuild -->
You can just include the js file the normal way.
<script src="path to the minified file"></script>
in your index.html.
Minified file is just like a normal JS file. What it does is:
It will merge all the mentioned JS files into a single file.
It will then minify it i.e it will remove the white spaces and auto change the variable names.
Advantage of this is you will have a lower size file and a single http request made from your browser which will help you load the page at a faster speed.
My index.html has split js files as follows:
<head>
....
<!-- build:js js/app1.min.js -->
<!-- js from lib -->
<script src="bower_components/angular/angular.min.js"></script>
<script src="bower_components/angular-route/angular-route.min.js"></script>
<!-- js of this app -->
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<!-- external js -->
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<!-- endbuild -->
....
</head>
.....
<body>
...
<!-- build:js js/app2.min.js -->
<!-- js from lib -->
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<!-- angular-animate provides search functionality -->
<!-- js of this app -->
<script src="js/filters.js"></script>
<script src="js/directives.js"></script>
<!-- endbuild -->
....
</body>
As you can see, I tried to use two sets of js files. The reason to split is performance. How to use usemin in this case. I tried with following:
'useminPrepare': {
'html': 'app/index.html'
},
'usemin': {
'html': ['dist/index.html']
},
However, there is no folder/file created. But in index.html, those two sections are replaced appropriately by app1.min.js and app2.min.js
Moreover, I do not understand one thing that all examples are using concat and uglify in combination of usemin. The files in index.html which are already *.min.js eg. files included in bower_components folder, what happens to them?
Unless you're heavily invested in grunt already, give gulp a look.
Below is a snippet from gulpfile.js. The gulp.src() functions take a list of files, then pipe them through transformations, ending with a list of files, which get's written to disk with gulp.dest().
This let's the first two blocks of code src, transform (minify,concat,etc), and write the js and css.
The last block of code src()'s the index.html, injects the filenames from the first two blocks, and writes the index.html to a build folder. I do consulting on gulp builds.
Here's how you'd do it in gulp:
// Vendor files are pre-minified. Get right versions.
// JS. Concat, and add revision if necessary
var srcJs = config.minify ? config.dashboard.vendorJsMin : config.dashboard.vendorJs;
var destJs = 'vendor' + (config.minify?'.min':'') + '.js';
var vendorJs = gulp.src(srcJs)
.pipe(plugins.if(config.concat, plugins.concat(destJs)))
.pipe(plugins.if(config.hash, plugins.hash()))
.pipe(gulp.dest(config.dashboard.dest + '/js'))
// Vendor files are pre-minified. Get right versions.
// CSS. Concat, and add revision if necessary
var srcCss = config.minify ? config.dashboard.vendorCssMin : config.dashboard.vendorCss;
var destCss = 'vendor' + (config.minify?'.min':'') + '.css';
var vendorCss = gulp.src(srcCss)
.pipe(plugins.if(config.concat, plugins.concat(destCss)))
.pipe(plugins.if(config.hash, plugins.hash()))
.pipe(gulp.dest(config.dashboard.dest + '/css'))
// Inject all these files into index.html
return gulp.src(config.dashboard.index)
.pipe(plugins.plumber())
.pipe(plugins.inject(vendorJs, _.merge({name: 'vendor'}, config.dashboard.injectOptions)))
.pipe(plugins.inject(vendorCss, _.merge({name: 'vendor'}, config.dashboard.injectOptions)))
.pipe(plugins.inject(appJs, _.merge({name: 'app'}, config.dashboard.injectOptions)))
.pipe(plugins.inject(appCss, _.merge({name: 'app'}, config.dashboard.injectOptions)))
.pipe(plugins.inject(templates, _.merge({name: 'templates'}, config.dashboard.injectOptions)))
.pipe(plugins.replace('REPLACE_NODE_ENV', config.NODE_ENV))
.pipe(gulp.dest(config.dashboard.dest))
This is a much more 'dev' like build system than grunt. Grunt is much more 'ops' like. Whatever works best is the one to use!