【问题标题】:Output an executable file with webpack使用 webpack 输出一个可执行文件
【发布时间】:2017-06-08 10:08:52
【问题描述】:

我目前正在编写一个节点 CLI 工具并使用 webpack 来捆绑我的所有资产。此应用程序的入口点是我实际解析 process.argv 并运行命令的 js 文件(作为参考,我使用的是 tj/commander)。这样,一旦捆绑完成,我可以输入./<outputFile>,它将运行我的应用程序。入口文件如下所示:

import cli from './cli';

cli.parse(process.argv);

// If nothing was supplied
if (!process.argv.slice(2).length) {
  cli.outputHelp();
}

捆绑工作正常,但我无法让 webpack 将文件输出为可执行文件。一旦我运行chmod +x <outputFile>,一切正常。有没有办法告诉 webpack 授予输出文件什么权限?

【问题讨论】:

    标签: node.js webpack


    【解决方案1】:

    一种简单的方法是使用 npm。你的项目中有package.json 吗? 将"build": "webpack && chmod +x outputFile" 添加到您的package.jsonscripts 部分,并通过运行npm run build 来构建您的项目。

    另一种方法是将这些解决方案之一添加到您的webpack.config.js

    无论你选择什么,你都需要添加这段代码:

    var chmod = require('chmod');
    chmod("outputFile", 500);
    

    【讨论】:

    • 我有,也没有考虑过这是一种选择。如果可能的话,我想把它全部保存在 webpack 中。如果没有其他人在第二天或第二天发布特定于 webpack 的解决方案,我会接受这个答案,因为它肯定会解决我的问题。
    【解决方案2】:

    虽然@oklas 的解决方案对我来说非常有效,但我真的很想尝试将所有这些都保留在 webpack 中。经过一番思考,我意识到这一切都可以通过一个非常简单的插件来完成:

    plugins: [
      // ...plugins,
    
      function() {
        this.plugin('done', () => {
          fs.chmodSync('bin/program-name.js', '755');
    
          // When the webpack output doesn't have a .js extension, minification fails :(
          fs.renameSync('bin/program-name.js', 'bin/program-name');
        })
      },
    ]
    

    使用适合您需要的方式!

    【讨论】:

      【解决方案3】:

      您需要在文件顶部附加#!/usr/bin/env node
      我最终使用 shelljs 得到了这个 webpack 插件

      plugins: [
        // ...plugins,
        function () {
            this.plugin('done', () => {
            shell
              .echo('#!/usr/bin/env node\n')
              .cat(`${__dirname}/build/outputfile.js`)
              .to(`${__dirname}/commandname`)
            shell.chmod(755, `${__dirname}/commandname`)
          })
        },
      ]
      

      【讨论】:

        【解决方案4】:

        我很惊讶没有人谈论 webpack 的 BannerPlugin。我做了和@oklas类似的事情,但是使用BannerPlugin添加特定节点shebang:

        {
          plugins: [
            new webpack.BannerPlugin({
              banner: '#!/usr/bin/env node',
              raw: true,
            }),
          ],
        }
        

        然后我只需添加执行权限,只需将chmod 添加到我的package.json 文件中:

        "scripts": {
          "build": "webpack && chmod +x dist/mycommand"
        }
        

        无论如何,如果您只想使用 webpack,您可以使用 WebpackShellPlugin,正如 oklas 所说(请注意,使用它会强制您添加新的依赖项,这就是我避免使用这种方法的原因):

        const WebpackShellPlugin = require('webpack-shell-plugin')
        {
          // [...]
          plugins: [
            new WebpackShellPlugin({
              onBuildEnd:['chmod +x dist/mycommand'],
            }),
          ],
        }
        

        如果你想避免包含WebpackShellPlugin作为依赖,你可以尝试定义一个基于fs的自定义插件,如@taylorc93所说

        【讨论】:

          【解决方案5】:

          这就是我使用 Webpack 5 的方式:

          import { promises as fs } from 'fs';
          
          plugins: [
              new webpack.BannerPlugin({
                  banner: '#!/usr/bin/env node',
                  raw: true,
                  entryOnly: true
              }),
              function() {
                  this.hooks.done.tapPromise('Make executable', async () => {
                      await fs.chmod(`${__dirname}/dist/app.js`, '755');
                  });
              }
          ]
          

          【讨论】:

            猜你喜欢
            • 2010-12-14
            • 1970-01-01
            • 1970-01-01
            • 2014-07-03
            • 2015-03-08
            • 1970-01-01
            • 2016-04-25
            • 2017-08-21
            • 1970-01-01
            相关资源
            最近更新 更多