Ionic 2更改main.js的名称(webpack.js output.filename设置)

Ionic 2更改main.js的名称(webpack.js output.filename设置),webpack,ionic2,ionic-cli,Webpack,Ionic2,Ionic Cli,我们有一个本机部署的Ionic 2应用程序,也可以部署到web上。构建时,我使用npm运行build--prod--release。这只是包装了爱奥尼亚的产品。 我正在尝试更新我们的构建过程,以便能够替换index.html中的默认main.js. 因此,我希望能够从以下位置更改此文件: <script src="build/main.js"></script> 当我构建时,我可以看到它正确地生成了源文件,但在完成爱奥尼亚构建后不久失败,并显示一条消息,说它找不到bui

我们有一个本机部署的Ionic 2应用程序,也可以部署到web上。构建时,我使用
npm运行build--prod--release
。这只是包装了爱奥尼亚的产品。

我正在尝试更新我们的构建过程,以便能够替换index.html中的默认
main.js.

因此,我希望能够从以下位置更改此文件:

<script src="build/main.js"></script>
当我构建时,我可以看到它正确地生成了源文件,但在完成
爱奥尼亚构建后不久
失败,并显示一条消息,说它找不到
build/main.js。
这是原始文件名,所以我想我需要让爱奥尼亚知道我正在更改main.js文件的名称

错误:


[11:00:32]生成产品失败:eNote:没有此类文件或目录,请打开
“/Users/work/client/www/build/main.js”
[11:00:32]爱奥尼亚应用程序脚本任务:“构建”
[11:00:32]错误:enoint:没有这样的文件或目录,请打开“/Users/work/client/www/build/main.js”

我不知道如何更新爱奥尼亚构建,以便它知道如何查找动态生成的main.js文件名。

编辑

更简单的解决方案,当ionic有许多更新时,不太可能损坏


所以用爱奥尼亚破坏缓存。这是一个骇人的解决方案,但目前还有效。问题是ionic构建系统有时抽象得太多了。早在10月份,就有人问是否有办法实现缓存破坏。离子队回应说,他们可能会考虑它在未来,但没有任何活动,因为… 因此,我将显示对webpack config和package.json的所有更改,然后解释所有内容

package.json的config部分应该如下所示

  "config": {
    "ionic_webpack": "./webpack.config.js",
    "ionic_source_map_type": "source-map",
    "ionic_uglifyjs": "./www/uglifyjs.config.json"
  }
对于webpack配置,您的输入和输出可以保持不变。确保您需要以下模块,然后您将需要添加以下插件:

var path = require('path'),
    fs = require('fs'),
    ManifestPlugin = require('webpack-manifest-plugin'),
    HtmlWebpackPlugin = require('html-webpack-plugin');

其中
updateFileName
如下所示

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 this to www because it's specific to the current
  // build and we don't want to commit it
  fs.writeFileSync(
    path.join(__dirname, 'www', 'uglifyjs.config.json'),
    JSON.stringify(uglifyConfig, null, 4)
  );
}
那么这里到底发生了什么?首先,在package.json中,我们必须为ionic构建过程生成一个新的uglify配置。您可以在构建的中间更改文件名,只要您将新的名称分配给<代码>进程.Env.IoiCixOutPuthJSfFielEngEng/<代码>,其余的构建就可以正常工作,除了丑陋的步骤仍然会寻找默认名称,<代码> Maul.js<代码>。我们将在下面看到如何生成它

现在我们要添加的三个插件

第一个有魔力。它确实是可配置的。如何设置,它采用默认的index.html,设置标题,为javascript输出注入一个
标记,然后将其写入您在filename属性中指定的位置。如果您使用的是来自ionic starter应用程序的默认index.html,那么您需要做的就是去掉
,它会自动将新链接放入文件名中,并在其中添加哈希

下一个插件为我们输出一个清单文件,这样我们就可以知道散列文件名是什么。默认情况下,它在
www/build/
中输出

下一个插件将新文件名分配给process.env.IONIC_OUTPUT_JS_file_name,并为我们生成新的uglify配置。基本上,我们获取输出的清单,将一个新的uglify配置写入www目录,然后根据从清单中获得的内容分配新的文件名

差不多就是这样。如果不想破坏开发人员的缓存,请保留html插件,去掉另外两个,然后将输出文件名更改回
process.env.IONIC\u output\u JS\u FILE\u NAME
。如果这样做,就根本不需要在
src/index.html
中引用主js文件。它将被放入您正在运行的开发或产品中。有关在不同环境中使用不同网页包设置的更多信息

更新:

对于离子3:

  • 确保您的
    tsconfig
    编译器选项中有这些设置:
  • “模块”:“es2015”,“目标”:“es5”

  • npm i cheerio--保存开发文件
  • 在您的网页配置中添加
    var cheerio=require('cheerio')
  • 摆脱网页包清单插件
  • updateFileName
    更改为以下内容:

    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);
      });
    }
    
  • 摆脱Html网页包插件

  • 在webpack配置的插件数组中放置以下函数以代替html插件:

    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()
    );
      });
    }
    
    函数updateIndexHTML(){
    这个插件(“完成”,函数(stats){
    var buildOutput=stats.toJson(),
    outputFileName=buildOutput[0],
    currentIndexHTML=fs.readFileSync(
    join(uu dirname,'src','index.html'),
    {编码:'utf8'}
    ),
    $=cheerio.load(currentIndexHTML);
    $('body')。追加(``);
    fs.writeFileSync(
    join(process.env.IONIC_WWW_DIR,'index.html'),
    $.html()
    );
    });
    }
    

  • 我从ionic论坛线程(,由aszmyd编写)中找到了一个更好的解决方案,该线程还解决了对main.css文件名进行散列的问题。我对脚本做了一些小的调整,因为我没有oauth.html或kajam.js

    此解决方案的优点是它不尝试拦截离子构建,而只对结果有效

    (毫无疑问,有人会对我发布这篇文章的方式感到不满,但这对我来说非常有用,我希望对其他人也是如此。我无法想象如果没有对所有css和js文件进行彻底的缓存破坏,就有一个web应用。)

    要运行此操作,只需添加:

    node <the-file-name.js>
    
    这与Ionic 2.x和3.x完美配合

    #!/usr/bin/env node
    
    var fs = require('fs'),
        path = require('path'),
        cheerio = require('cheerio'),
        revHash = require('rev-hash');
    
    /**
     *
     * @param string fileName
     * @returns string
     */
    function hashFile(file) {
    
        // Get file name
        var fileName = file.replace(/\.[^/.]+$/, "");
        // Get file extension
        var re = /(?:\.([^.]+))?$/;
        var fileExtension = re.exec(file)[1];
    
        var filePath = path.join(buildDir, file);
        var fileHash = revHash(fs.readFileSync(filePath));
        var fileNewName = `${fileName}.${fileHash}.${fileExtension}`;
        var fileNewPath = path.join(buildDir, fileNewName);
        var fileNewRelativePath = path.join('build', fileNewName);
        //Rename file
        console.log("cache-busting.js:hashFile:Renaming " + filePath + " to " + fileNewPath);
        fs.renameSync(filePath, fileNewPath);
    
        return fileNewRelativePath;
    }
    
    
    var rootDir = path.resolve(__dirname);
    var wwwRootDir = path.resolve(rootDir, 'www');
    var buildDir = path.join(wwwRootDir, 'build');
    var indexPath = path.join(wwwRootDir, 'index.html');
    $ = cheerio.load(fs.readFileSync(indexPath, 'utf-8'));
    
    $('head link[href="build/main.css"]').attr('href', hashFile('main.css'));
    $('body script[src="build/main.js"]').attr('src', hashFile('main.js'));
    $('body script[src="build/polyfills.js"]').attr('src', hashFile('polyfills.js'));
    $('body script[src="build/vendor.js"]').attr('src', hashFile('vendor.js'));
    
    fs.writeFileSync(indexPath, $.html());
    

    我已经把它放在我们的项目@Nix中了,这样你就可以在那里查看:)。嗨,使用你的代码Ionic v3,它构建的很好,但是它不会散列文件。我必须更改什么来散列文件?我已尝试设置进程。env.i
    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()
    );
      });
    }
    
    node <the-file-name.js>
    
    #!/usr/bin/env node
    'use strict';
    
    var md5File = require('md5-file'),
        fs = require('fs');
    
    /**
     * This script renames files inside platforms/browser/www/ folder and updates their references in html files like index.html
     * The mechanism is for improve caching. So file like `main.js` will be renamed to `main.[FILE-MD5-HASH].js` and its references
     * in html files will be updated.
     */
    var buildFolder = 'www/';
    var assetsFolder = buildFolder + 'build/';
    
    var jsFiles = [
        'main'
    ];
    var cssFiles = [
        'main'
    ];
    var htmlFilesToUpdate = [
        'index.html'
    ];
    var replacements = [];
    
    jsFiles.forEach(function (file) {
        var hash = md5File.sync(assetsFolder + file + '.js');
        renameFile(file + '.js', file + '.' + hash + '.js');
    });
    
    cssFiles.forEach(function (file) {
        var hash = md5File.sync(assetsFolder + file + '.css');
        renameFile(file + '.css', file + '.' + hash + '.css');
    });
    htmlFilesToUpdate.forEach(function (htmlFile) {
        console.log('Update "' + htmlFile + '" with new file revisions.');
        console.log('Replacements: ' + JSON.stringify(replacements));
        replacements.forEach(function (replacementObject) {
            replaceInFile(buildFolder + htmlFile, replacementObject.from, replacementObject.to);
        });
    });
    
    function renameFile(input, output) {
        console.log('Rename "' + input + '" to "' + output + '"');
        fs.rename(assetsFolder + input, assetsFolder + output);
        if (fs.existsSync(assetsFolder + input + '.map')) {
            console.log('Rename "' + input + '.map" to "' + output + '.map"');
            fs.rename(assetsFolder + input + '.map', assetsFolder + output + '.map');
        }
        replacements.push({from: input, to: output});
    }
    
    function replaceInFile(file, regex, replacement) {
        var fileContents = fs.readFileSync(file, 'utf-8');
        fs.writeFileSync(file, fileContents.replace(regex, replacement), 'utf8');
    }
    
    #!/usr/bin/env node
    
    var fs = require('fs'),
        path = require('path'),
        cheerio = require('cheerio'),
        revHash = require('rev-hash');
    
    /**
     *
     * @param string fileName
     * @returns string
     */
    function hashFile(file) {
    
        // Get file name
        var fileName = file.replace(/\.[^/.]+$/, "");
        // Get file extension
        var re = /(?:\.([^.]+))?$/;
        var fileExtension = re.exec(file)[1];
    
        var filePath = path.join(buildDir, file);
        var fileHash = revHash(fs.readFileSync(filePath));
        var fileNewName = `${fileName}.${fileHash}.${fileExtension}`;
        var fileNewPath = path.join(buildDir, fileNewName);
        var fileNewRelativePath = path.join('build', fileNewName);
        //Rename file
        console.log("cache-busting.js:hashFile:Renaming " + filePath + " to " + fileNewPath);
        fs.renameSync(filePath, fileNewPath);
    
        return fileNewRelativePath;
    }
    
    
    var rootDir = path.resolve(__dirname);
    var wwwRootDir = path.resolve(rootDir, 'www');
    var buildDir = path.join(wwwRootDir, 'build');
    var indexPath = path.join(wwwRootDir, 'index.html');
    $ = cheerio.load(fs.readFileSync(indexPath, 'utf-8'));
    
    $('head link[href="build/main.css"]').attr('href', hashFile('main.css'));
    $('body script[src="build/main.js"]').attr('src', hashFile('main.js'));
    $('body script[src="build/polyfills.js"]').attr('src', hashFile('polyfills.js'));
    $('body script[src="build/vendor.js"]').attr('src', hashFile('vendor.js'));
    
    fs.writeFileSync(indexPath, $.html());