ionic2 - Ionic 2 change name of main.js ( webpack.js output.filename setting) -
we have ionic 2 app deployed natively , web. when building use npm run build --prod --release
. wraps ionic build.
i'm trying update our build process able swap out default main.js.
in index.html
so want able change file from:
<script src="build/main.js"></script>
with (autogenerated hash)
<script src="build/main.7b297e8f7d1c2760a1bc.js"></script>
step 1 generate file. able generate right file each build using webpack output.filename setting.
module.exports = { entry: [process.env.ionic_app_entry_point, './web.config', './src/ai.min.js'], output: { path: '{{build}}', filename: '[name].[chunkhash].js',
when build can see it's correctly generating source file shortly after completing ionic build
fails message saying can't find build/main.js.
original file name think need somehow let ionic know i'm changing name of main.js file.
error:
[11:00:32] build prod failed: enoent: no such file or directory, open '/users/work/client/www/build/main.js' [11:00:32] ionic-app-script task: "build" [11:00:32] error: enoent: no such file or directory, open '/users/work/client/www/build/main.js'
i'm not sure how update ionic build
knows dynamically generated main.js filename.
so cache busting ionic. it's hackish solution works now. problem ionic build system abstracts little @ times. in october, asked if there way implement cache busting. ionic team responded might consider in future, there hasn't been activity on since. here's github issue.
so i'll show changes webpack config , package.json , explain everything.
the config section of package.json should this.
"config": { "ionic_webpack": "./webpack.config.js", "ionic_source_map_type": "source-map", "ionic_uglifyjs": "./www/uglifyjs.config.json" }
for webpack config, entry , output can remain same. make sure have required following modules , you'll want add following plugins:
var path = require('path'), fs = require('fs'), manifestplugin = require('webpack-manifest-plugin'), htmlwebpackplugin = require('html-webpack-plugin');
...
plugins: [ new htmlwebpackplugin({ filename: './../index.html', inject: 'body', template: './src/index.html', title: 'my app', }), new manifestplugin(), updatefilename ]
where updatefilename
follows
function updatefilename() { this.plugin("done", function() { var manifest = require(process.env.ionic_build_dir + '/manifest.json'), filename = process.env.ionic_output_js_file_name; updateuglifyconfig(filename, manifest); process.env.ionic_output_js_file_name = manifest[filename]; }); } function updateuglifyconfig(filename, manifest) { var uglifyconfig = { sourcefile: manifest[filename], destfilename: manifest[filename], insourcemap: manifest[filename + '.map'], outsourcemap: manifest[filename + '.map'], mangle: true, compress: true, comments: true }; // we're writing www because it's specific current // build , don't want commit fs.writefilesync( path.join(__dirname, 'www', 'uglifyjs.config.json'), json.stringify(uglifyconfig, null, 4) ); }
so what's happening here? fist off, in package.json, going have generate new uglify config ionic build process. can change file name in middle of build , long assign new name process.env.ionic_output_js_file_name
rest of build work fine, except uglify step still default name, main.js
. we'll see how generate below.
now 3 pluggins we're adding.
the first 1 magic. it's configurable. how it's set up, takes default index.html, sets title, injects <script>
tag javascript output, , write's you've specified in filename property. if you're using default index.html comes ionic starter app, need rid of <script src="build/main.js"></script>
, it'll automagically put new link in filename hash in it. docs here.
the next plugin outputs manifest file can know filename hash. default, outputs in www/build/
. docs here.
the next plugin assigns new file name process.env.ionic_output_js_file_name , generates new uglify config us. pretty grab manifest output, write new uglify config www directory, , assign new file name got out of manifest.
so pretty that's it. if don't want cache busting dev, keep html pluggin, rid of other two, , change output filename process.env.ionic_output_js_file_name
. if this, wont need reference main js file in src/index.html
@ all. it'll put in whether running dev or prod. more info on using different webpack settups different environments, check out.
update:
for ionic 3:
- make sure have these settings in
compileroptions
oftsconfig
:
"module": "es2015", "target": "es5"
npm cheerio --save-dev
- in webpack config add
var cheerio = require('cheerio')
- get rid of webpack manifest plugin.
change
updatefilename
following:function updatefilename() { this.plugin("done", function(stats) { var buildoutput = stats.tojson()['assetsbychunkname']['main'], filename = process.env.ionic_output_js_file_name, manifest = { [filename]: buildoutput[0], [filename + '.map']: buildoutput[1] }; updateuglifyconfig(filename, manifest); process.env.ionic_output_js_file_name = manifest[filename]; console.log('ionic_output_js_file_name', process.env.ionic_output_js_file_name); }); }
get rid of html webpack plugin
in place of html plugin, put following function in plugins array in webpack config:
function updateindexhtml() { this.plugin("done", function(stats) { var buildoutput = stats.tojson()['assetsbychunkname']['main'], outputfilename = buildoutput[0], currentindexhtml = fs.readfilesync( path.join(__dirname, 'src', 'index.html'), { encoding: 'utf8' } ), $ = cheerio.load(currentindexhtml); $('body').append(`<script src="build/${outputfilename}"></script>`); fs.writefilesync( path.join(process.env.ionic_www_dir, 'index.html'), $.html() ); }); }
Comments
Post a Comment