How to npm publish specific folder but as package root

后端 未结 10 1279
后悔当初
后悔当初 2020-12-13 01:10

I have a project that include a gulp task for building and packaging the sources and release in a directory called dist. My goal is publish it as a npm package,

10条回答
  •  我在风中等你
    2020-12-13 01:52

    I have a similar problem to the original poster (@robsonrosa). In my case I use typecript which compiles to a dist directory. While I could make typescript compile to the root directory I think the best solution is to generate a separate package.json file in the dist directory.
    This is similar to @scvnc suggestion of copying the package.json but with a twist:

    As part of the packaging process you should generate a package.json for the package which is based on but distinct from the main package.json file in the root directory

    The rationale:

    • The root package.json file is the development file. It may contain scripts or development dependencies that are of no use to the package user, but may pose security concerns for you. Your packaging procedure may include code that strips that information from the production package.json.
    • You may want to deploy your package to different environments which may require different package files (e.g. you may want to have different versions or dependencies).

    --- EDIT ---

    I was asked for a solution in the comments. So here is some code I am using. This should be considered as an example it is not meant to be generic and is specific to my projects.

    My setup:

    package.json         - main package.json with dev dependencies and useful scripts.
    .npmignore           - files to ignore; copied to 'dist' directory as part of the setup.
    /src                 - directory where my typescript code resides.
    /src/SetupPackage.ts - bit of code used to setup the package.
    /dist                - destination directory for the compiled javascript files.
    

    I want to package only the dist directory and the directory should be the root directory in the package.

    The file SetupPackage.ts in my src directory will be compiled to SetupPackage.js in the dist directory by typescript:

    import fs from "fs";
    
    // DO NOT DELETE THIS FILE
    // This file is used by build system to build a clean npm package with the compiled js files in the root of the package.
    // It will not be included in the npm package.
    
    function main() {
        const source = fs.readFileSync(__dirname + "/../package.json").toString('utf-8');
        const sourceObj = JSON.parse(source);
        sourceObj.scripts = {};
        sourceObj.devDependencies = {};
        if (sourceObj.main.startsWith("dist/")) {
            sourceObj.main = sourceObj.main.slice(5);
        }
        fs.writeFileSync(__dirname + "/package.json", Buffer.from(JSON.stringify(sourceObj, null, 2), "utf-8") );
        fs.writeFileSync(__dirname + "/version.txt", Buffer.from(sourceObj.version, "utf-8") );
    
        fs.copyFileSync(__dirname + "/../.npmignore", __dirname + "/.npmignore");
    }
    
    main();
    

    This file:

    • Copies the root package.json but removes the scripts and dev dependencies which are not needed in the package. It also fixes the main entry point to the package.
    • Writes the version of the package from package.json to a file called version.txt.
    • Copies the .npmignore package from the root.

    The .npmignore content is:

    *.map
    *.spec.*
    SetupPackage.*
    version.txt
    

    I.e. unit tests (spec files) and typescript map files are ignored as well as the SetupPackage.js file and the version.txt file it creates. This leaves a clean package.

    Finally the main package.json file has the following scripts for use by the build system (assumes sh is used as the shell).

    "scripts": {
        "compile": "tsc",
        "clean": "rm -rf dist",
        "prebuildpackage": "npm run clean && npm run compile && node dist/SetupPackage.js",
        "buildpackage": "cd dist && npm pack"
      },
    

    To build the package the build system clones the repo, does npm install and then runs npm run buildpackage which in turn:

    • Deletes the dist directory ensuring a clean compile.
    • Compiles the typescript code to javascript.
    • Executes the SetupPackage.js file which prepares dist for packaging.
    • cds to the dist directory and builds the package there.

    I use the version.txt file as an easy way to get the version in package.json and to tag my repo. There are countless other ways to do this or you may want to auto-increment the version. Remove this from SetupPackage.ts and .npmignore if it is not useful to you.

提交回复
热议问题