facebook / create-react-app

Set up a modern web app by running one command.
https://create-react-app.dev
MIT License
102.71k stars 26.85k forks source link

Source License notice strip #6441

Open ghost opened 5 years ago

ghost commented 5 years ago

I have a project, for example:

Example
package.json ```json { "...": "", "main": "index.js", "scripts": { "...": "", "build": "react-scripts build" }, "dependencies": { "...": "", "react-scripts": "2.1.5" } } ``` index.js ```js /*! * project * Copyright 2019 Igor Vuchastyi * Licensed under MIT */ // Some other code ```


When i run npm run build it executes react-scripts build, then it creates build directory like this build/static/{css,js}/*.{css,js}.
JS files doesn't contain any license i have specified at the index.js. If i do it with webpack - webpack collect my license and put at the top of bundle.

I think react-scripts strips my license from bundle and from other packages.

My problem: i don't want use react-scripts eject, i don't want use any other which is forks of react-scripts or etc.
My question: is there a way to leave my License notice at top of each chunk produced by react-scripts?
I was searching for around 2 hours. Was googling, was searching in this repository. Found nothing about this thread.

iansu commented 5 years ago

I think this is an issue with our terser config.

ianschmitz commented 5 years ago

This looks like it may help: https://github.com/webpack-contrib/terser-webpack-plugin#preserve-comments

ghost commented 5 years ago

I have figured out. I don't have @license tag in my JSDoc, but is that so important to place this tag at license notice (i understand that if i haven't placed this tag - my license notice will be stripped)?

I can point to a very popular projects which doesn't use @license tag for license notice, for example: react, react-scripts, bootstrap.

BTW, you can use this repository for testing.

ghost commented 5 years ago

Owww... I have found out that i was wrong. react-scripts just remove all comments from source files, which causes the issue.

After some research (thanks @ianschmitz), i can say that this issue is really related with terser config, as pointed by @iansu.

I would like to submit PR, but there much ways to fix this issue and i don't know which suits most for React Community.

So, the ways:

  1. I can modify terser options at https://github.com/facebook/create-react-app/blob/df3e73f454f718dbb3f928ecf681a50467e5a18d/packages/react-scripts/config/webpack.config.js#L215 with comments: /^!|\*!/, \ Advantages: it will place copyright notices inside chunks. Disadvantages: all copyright notices will be placed somewhere in the middle of chunks (not at top of the file). It will also keep copyright notices of other packages such as object-assign, React, etc. Not all chunks will contain project copyright notice, only those which source contain this notice (it's boring to include it in each file).
  2. I can modify terser config at https://github.com/facebook/create-react-app/blob/df3e73f454f718dbb3f928ecf681a50467e5a18d/packages/react-scripts/config/webpack.config.js#L227 with extractComments: /^!|\*!/, }), \ Advantages: it will place comment at top of each chunk like 'License information can be found in chunk.LICENSE'. Will be created file chunk.LICENSE, this file will contain information about used licenses. Disadvantages: chunks will not contain copyright notices (it will contain only comment which will reference to real file where licenses are stored). Also it will keep copyright notices of other packages such as object-assign, React, etc. Not all chunk license files will contain project copyright notice, only those which source contain this notice (it's boring to include it in each file).
  3. Create scripts/build.js file inside main project (it should be created by user, not by package). In this file transfer whole copyright notice into env variable like REACT_APP_COPYRIGHT_NOTICE=/* Copyright 2019-present ... \n * Licensed under MIT \n */ react-scripts build. \ Use it like "build": "scripts/build.js". \ And then in react-scripts catch this env variable like https://github.com/facebook/create-react-app/blob/df3e73f454f718dbb3f928ecf681a50467e5a18d/packages/react-scripts/config/webpack.config.js#L39 and use to display before each chunk. Also it can be configured via dotenv files and without scripts/build.js file. \ Advantages: it will place project copyright notice as needed. Disadvantages: currently i don't know way to place env var at the top of each chunk.
ghost commented 5 years ago

Any comments?

iansu commented 5 years ago

Option 1 sounds like the best choice to me.

ianschmitz commented 5 years ago

This could potentially have a negative impact on bundle size. Are we sure we want this to be the default for all users?

dynamis commented 5 years ago

Larger bundle size is better than license violation especially in case of the default option.

I'll suggest more options and I believe option 5 can solve both legal and bundle size problems:

1'. Keep (more) legal comments in chunk js file.

Same as option 1 but use different regexp. /^\**!|@preserve|@license|@cc_on/i for comments option. This is the default regexp of extractComments config of terser-webpack-plugin and this can keep most of legal notice comments.

2'. Extract (more) legal comment into chunk.LICENSE file.

Same as option 2 but use default regexp (/^\**!|@preserve|@license|@cc_on/i) of terser-webpack-plugin with adding extractComments: true.

see: https://github.com/webpack-contrib/terser-webpack-plugin#extractcomments

4. Extract legal comments and preserve @license comments.

We can preserve @license comments in chunk js file and extract other legal (i.e. /^**!|@preserve|@license|@cc_on/i) comments into chunk.LICENSE file with terser config like this:

      new TerserPlugin({
        terserOptions: {
          output: {
            comments: /@license/i,
          },
        },
        extractComments: true,
      }),

This comes from example usage of terser-webpack-plugin: https://github.com/webpack-contrib/terser-webpack-plugin#preserve-comments

5. Extract legal comments and add link to it from top of chunk js file.

Extract legal comments with extractComments: true terser option to make chunk.LICENSE file (same as option 2') and add 1 line legal comment on top of the chunk js files:

/*! Create React App vX.X.X | (c) Facebook and other contributors | see chunk.LICENSE file for more license information */

This is the similar approach as jQuery:

/*! jQuery v3.3.1 | (c) JS Foundation and other contributors | jquery.org/license */
dynamis commented 5 years ago

Sorry, option 5 is actually same as option 2'. Option 2' will automatically add license notice comment on top of the chunk.js file. Option 2' can solve both legal and bundle size problem.

1st line of the chunk.js file generated with extractComments: true option will be:

/*! For license information please see 2.xxxxxxxx.chunk.js.LICENSE */

and 2.xxxxxxxx.chunk.js.LICENSE file will be:

/*
object-assign
(c) Sindre Sorhus
@license MIT
*/

/** @license React v16.8.4
 * react.production.min.js
 *
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

/** @license React v16.8.4
 * react-dom.production.min.js
 *
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

/** @license React v0.13.4
 * scheduler.production.min.js
 *
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
dynamis commented 4 years ago

note: workaround for existing versions.

once you install the npm modules, you can customize installed node_modules to change the webpack config of CRA to enable extractComments option:

node_modules/react-scripts/config/webpack.config.js

      minimizer: [
        // This is only used in production mode
        new TerserPlugin({
          terserOptions: {
             ...snip...
          },
             ...snip...
          parallel: !isWsl,
          // Enable file caching
          cache: true,
          sourceMap: shouldUseSourceMap,
+         extractComments: true,
        }),

Then you can get build/static/js/2.xxxxxxx.chunk.js.LICENSE file as I show above.

One more fix needed (on react-dom side?)

I noticed minified artifact of react-dom keep the license notice about Modernizr 3.0.0pre (Custom Build): https://unpkg.com/browse/react-dom@16.12.0/umd/react-dom.production.min.js But it will not be kept on 2.xxxxxxx.chunk.js.LICENSE file since it doesn't match the default regexp of the extractComments option.

nana4gonta commented 4 years ago

extractComments option is true by default in v2.0.0 (released in 2019-09-05). And, terser-webpack-plugin has been updated in create-react-app v3.3.0 (released in 2019-12-04). But it does not yet include the Modernizr license notice. So, my workaround is as follows.

node_modules/react-scripts/config/webpack.config.js

      minimizer: [
        // This is only used in production mode
        new TerserPlugin({
          terserOptions: {
            ...snip...
          },
          sourceMap: shouldUseSourceMap,
+         extractComments: /^\**!|@preserve|@lic|@cc_on|Modernizr/i,
       })
codepunkt commented 4 years ago

I'm completely baffled by this issue and sad i missed out on this last year.

Usually, packages licenses are communicated by the "license" field in their package.json and might have accompanying license text with copyrights in a toplevel LICENSE file. You can use webpack-license-plugin to extract all license information of your create react app into a so-called "Bill of Materials" that you can then distribute with your built application (without any comments being left in the build output for performance reasons).

Why do you still want to keep license comments in the bundled output?

Please explain!

johnnyreilly commented 4 years ago

I ended up blogging about this: https://blog.johnnyreilly.com/2020/01/license-to-kill-your-pwa.html

I got a response from @sokra suggesting making a change so the default output file name is LICENSE.txt instead of LICENSE

https://www.twitter.com/johnny_reilly/status/1220099377437532161

See https://github.com/webpack-contrib/terser-webpack-plugin/blob/0e2da43f7bce3716bd6418b7f484d959e2f97172/src/index.js#L294

codepunkt commented 4 years ago

Hello there, @codepunkt ,

The comments inside the .html, .css, .js indeed raise the performance issue. What we would like, would be to have a way of keeping just some "tagged"/"marked" comments. For example, if I build for my client a custom app, I, or my client, maybe would like to keep a copyright comment on the code. That way, we could protect our code from frauds, like somebody just copying the source code of what I just wrote and resell it someone else as theirs. So those comments could help in protecting the intellectual property of the code.

Best, Manu

I'm not sure i understand. How will a comment in production build output code help you protect your intellectual property? You need to distribute your code under a license, and there's other ways of transporting the information about that (regardless if its an open source license or a commerical one).

Depending on your code-splitting setup, your webpack build will produce one or more output chunks. If we somehow magically "keep" specific comments from the build input, those might end up anywhere. If you really need comments at the top of your webpack output chunks, consider using the webpack banner plugin for that.

MK11MK commented 4 years ago

Thank you all for contribution. This is really helpful.

I am stuck with injecting @license /@copyright statement from a "xxx.txt" file to html codes.. is there any setting or plugin for the same. Please advise.

codepunkt commented 4 years ago

@MK11MK why are you doing this?

dawnmist commented 4 years ago

I've just arrived here because of a need to remain compliant with the attribution requirements for font-awesome. The comments are being stripped from where they were required to remain in the bundle.

So the answer to "why" is because I'm legally required to leave those comments alone, for them to remain in the bundle. From: https://fontawesome.com/license/free

Attribution Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font Awesome Free files already contain embedded comments with sufficient attribution, so you shouldn't need to do anything additional when using these files normally.

We've kept attribution comments terse, so we ask that you do not actively work to remove them from files, especially code. They're a great way for folks to learn about Font Awesome.

Removing them all to the num.chunk.xxxxx.LICENSE.txt files is removing them from the code, and thus is not actually compliant with the license Attribution requirements for their use.