繁体   English   中英

Webpack 3 + babel仅在条目不高于./webpack.config.js时进行解析

[英]Webpack 3 + babel only parsing when entry is NOT higher than ./webpack.config.js

我正在构建一个脚手架引擎来启动Django后端+ React前端站点。 我还采用了多页应用程序方法,而不是SPA,所以事情有点...不合常规。

我向您展示该脚手架的最终结果,因为问题似乎出在我的webpack或babel配置以及我给他们的输入组件的位置。

因此,首先,此文件结构确实起作用,react组件在Django的服务器上呈现精美。

node/
    package.json
    .babelrc
    webpack.config.js
    /src
        /Home.js (<- the react component)
    ...
www/
    manage.py
    www/
         templates/
             home.html
         dist/
             home.js (<- webpack's output)
...

但是我更喜欢这样,其中组件更靠近django template.html文件:

node/
    package.json
    .babelrc
    webpack.config.js
    ...
www/
    manage.py
    www/
         templates/
             home.html
             react/
                  components/
                  containers/
                      Home.js (<- the react component)
         dist/
             home.js (<- webpack's output)

但是,我现在收到一个构建错误,当它看到JSX时会抱怨-好像babel根本没有将其填充。

我唯一更改的是该组件不再位于node /目录下(显然,我更新了webpack.config.js中的路径以反映这一点)

我认为这不是webpack找到正确路径的问题。 因为它正在读取模板目录中的组件,并且仍将分发包正确放置在dist目录中。 但这不是polyfilling,结果输出文件已损坏。 我不只是说它被丑化了,我是说它已经完全坏掉了(见下文)

甚至有可能做我想做的事情?

细节

当我运行'npm run build'来运行webpack时出现错误:

ERROR in ../www/www/templates/react/containers/HomeContainer.js
Module build failed: SyntaxError: Unexpected token (6:2)

  4 | const Home = props => {
  5 |   return (
> 6 |       <div>

babelrc

{
    "presets": ["env", "react"]
}

webpack.config.js

const webpack = require('webpack'); //to access built-in plugins
const path = require('path');

// This one works
// let ent = "./HomeContainer.js"

// This one does NOT work
let ent = "../www/www/templates/react/containers/HomeContainer.js"

let out = "../www/www/static/dist/js/Home"

module.exports = {
    entry: {
        [out]: ent
    },
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, './'),
    },
    module: {
        rules: [
            { test: /\.css$/,  exclude: /node_modules/, use: 'css-loader' },
            { test: /\.scss$/, exclude: /node_modules/, use: 'sass-loader' },
            { test: /\.(js|jsx)$/, exclude: /node_modules/, loader: "babel-loader" }
        ],
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin(),
    ],
}

的package.json

{
    "name": "frontend",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "test": "echo 'Error: no test specified' && exit 1",
        "build": "webpack"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "babel-cli": "^6.24.1",
        "babel-core": "^6.25.0",
        "babel-loader": "^7.1.1",
        "babel-preset-env": "^1.6.0",
        "babel-preset-react": "^6.24.1",
        "css-loader": "^0.28.4",
        "node-sass": "^4.5.3",
        "sass-loader": "^6.0.6",
        "webpack": "^3.1.0"
    },
    "dependencies": {
        "react": "^15.6.1",
        "react-dom": "^15.6.1"
    }
}

损坏的dist / home.js

!function(m){function t(e){if(n[e])return n[e].exports;var r=n[e]={i:e,l:!1,exports:{}};return m[e].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};t.m=m,t.c=n,t.d=function(m,n,e){t.o(m,n)||Object.defineProperty(m,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(m){var n=m&&m.__esModule?function(){return m.default}:function(){return m};return t.d(n,"a",n),n},t.o=function(m,t){return Object.prototype.hasOwnProperty.call(m,t)},t.p="",t(t.s=0)}([function(m,t){throw new Error("Module build failed: SyntaxError: Unexpected token (6:2)\n\n[0m [90m 4 | [39m[36mconst[39m [33mHome[39m [33m=[39m props [33m=>[39m {\n [90m 5 | [39m\t[36mreturn[39m (\n[31m[1m>[22m[39m[90m 6 | [39m\t\t[33m<[39m[33mdiv[39m[33m>[39m\n [90m   | [39m\t\t[31m[1m^[22m[39m\n [90m 7 | [39m\t\t\t[33m<[39m[33mh1[39m[33m>[39m[33mHome[39m page [36mfor[39m { window[33m.[39mprops[33m.[39mproject_title }[33m<[39m[33m/[39m[33mh1[39m[33m>[39m\n [90m 8 | [39m\t\t\t[33m<[39m[33mp[39m[33m>[39m[33mTo[39m edit [36mthis[39m page[33m,[39m you[32m'll find the react component at /frontend/src/root/Home.js</p>[39m\n [90m 9 | [39m\t\t[33m<[39m[33m/[39m[33mdiv[39m[33m>[39m[0m\n")}]);

起作用的dist / home.js

!function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=81)}([function(e,t){function n(){throw new Error("setTimeout has not been defined")}function o(){throw new Error("clearTimeout has not been defined")}function r(e){if(l===setTimeout)return setTimeout(e,0);if((l===n||!l)&&setTimeout)return l=setTimeout,setTimeout(e,0);try{return l(e,0)}catch(t){try{return l.call(null,e,0)}catch(t){return l.call(this,e,0)}}}function i(e){if(p===clearTimeout)return clearTimeout(e);if((p===o||!p)&&clearTimeout)return p=clearTimeout,clearTimeout(e);try{return p(e)}catch(t){try{return p.call(null,e)}catch(t){return p.call(this,e)}}}function a(){m&&f&&(m=!1,f.length?h=f.concat(h):v=-1,h.length&&s())}function s(){if(!m){var e=r(a);m=!0;for(var t=h.length;t;){for(f=h,h=[];++v<t;)f&&f[v].run();v=-1,t=h.length}f=null,m=!1,i(e)}}function u(e,t){this.fun=e,this.array=t}function c(){}var l,p,d=e.exports={};!function(){try{l="function"==typeof setTimeout?setTimeout:n}catch(e){l=n}try{p="function"==typeof clearTimeout?clearTimeout:o}catch(e){p=o}}();var f,h=[],m=!1,v=-1;d.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];h.push(new u(e,t)),1!==h.length||m||r(s)},u.prototype.run=function(){this.fun.apply(null,this.array)},d.title="browser",d.browser=!0,d.env={},d.argv=[],d.version="",d.versions={},d.on=c,d.addListener=c,d.once=c,d.off=c,d.removeListener=c,d.removeAllListeners=c,d.emit=c,d.prependListener=c,d.prependOnceListener=c,d.listeners=function(e){return[]},d.binding=function(e){throw new Error("process.binding is not supported")},d.cwd=function(){return"/"},d.chdir=function(e){throw new Error("process.chdir is not supported")},d.umask=function(){return 0}},function(e,t,n){"use strict";(function(t){function n(e,t,n,r,i,a,s,u){if(o(t),!e){var c;if(void 0===t)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[n,r,i,a,s,u],p=0;c=new Error(t.replace(/%s/g,function(){return l[p++]})),c.name="Invariant Violation"}throw c.framesToPop=1,c}}var o=function(e){};"production"!==t.env.NODE_ENV&&(o=function(e){if(void 0===e)throw new Error("invariant requires an error message argument")}),e.exports=n}).call(t,n(0))},function(e,t,n){"use strict";(function(t){var o=n(9),r=o;if("production"!==t.env.NODE_ENV){var i=function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),o=1;o<t;o++)n[o-1]=arguments[o];var r=0,i="Warning: "+e.replace(/%s/g,function(){return n[r++]});"undefined"!=typeof console&&console.error(i);try{throw new Error(i)}catch(e){}};r=function(e,t){if(void 0===t)throw new Error("`warning(condition, format, ...args)` requires a warning message argument");if(0!==t.indexOf("Failed Composite propType: ")&&!e){for(var n=arguments.length,o=Array(n>2?n-2:0),r=2;r<n;r++)o[r-2]=arguments[r];i.apply(void 0,[t].concat(o))}}}e.exports=r}).call(t,n(0))},function(e,t,n){"use strict";function o(e){for(var t=arguments.length-1,n="Minified React error #"+e+"; visit http://facebook.github.io/react/docs/error-decoder.html?invariant="+e,o=0;o<t;o++)n+="&args[]="+encodeURIComponent(arguments[o+1]);n+=" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.";var r=new Error(n);throw r.name="Invariant Violation",r.framesToPop=1,r}e.exports=o},function(e,t,n){"use strict";function o(e){if(null===e||void 0===e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}/*

问题是Babel会寻找最接近要.babelrc文件的.babelrc 这意味着它将在文件目录中查找并开始爬升目录树,直到找到一个或到达文件系统的根目录为止。 但是,由于您的node目录是www的同级目录,因此您的源代码就位于该.babelrc ,因此找不到.babelrc ,因此不会应用您的预设。

您可以babel-loader配置选项 ,无论使用什么目录,都可以使用这些选项 不幸的是,您会遇到模块分辨率问题,默认情况下该模块Node模块分辨率相同。 导入模块后,将在node_modules目录中搜索该node_modules ,如果在该目录中找不到该模块,则它将在父目录(即../node_modules )中../node_modules ,依此类推。 这与Babel使用的行为相同,并且在Node中的工具中非常常见。

可以将预设导入配置中,因此不会从正在编译的文件中解析这些预设。

{
  test: /\.(js|jsx)$/,
  exclude: /node_modules/,
  loader: 'babel-loader',
  options: {
    presets: [
      // Need to require them, so they are resolved from this config,
      // otherwise they are resolved from the directory of the file that
      // is being transpiled.
      require('babel-preset-env'),
      require('babel-preset-react')
    ]
  }
}

除此之外,您还将面临解决使用npm安装的任何模块的问题,因为它们再次位于同级目录中,并且找不到。 的WebPack允许您解决与resolve.module

resolve: {
  modules: [
    // Also look for modules next to the webpack config, because dependencies
    // like `react` are installed here, not where the components are.
    path.resolve(__dirname, 'node_modules'),
    'node_modules'
  ],
}

即使可行,我还是强烈建议您不要采用这种结构。 毕竟,这是webpack中的一种解决方法,如果您想添加任何其他工具,则很可能会遇到问题。

最重要的部分是节点模块应位于项目的根目录中,而要使用它们的任何内容都将位于子目录中。 像这样:

.
├─ .babelrc
├─ manage.py
├─ package.json
├─ webpack.config.js
└─ www
   ├─ dist
   │  └─ bundle.js
   └─ templates
      ├─ home.html
      └─ react
         ├─ components
         └─ containers
            └─ Home.js

这样一来,您无需进行任何处理,就可以确保从npm安装的任何模块都可以使用。 此外,无论项目是安装npm软件包,运行webpack还是运行python构建,您都可以从项目的根目录运行所有内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM